절차 지향과 객체 지향
절차 지향(Procedure-oriented)은, 기능중심으로 "무엇을 어떠한 절차로 할 것인가?"가 핵심이다. 어떤 기능을 어떤 순서로 처리하는가에 초점을 둔다.
객체 지향(Object-oriented)은, 객체중심으로 "누가 어떠한 일을 할 것인가?"가 핵심이다. 객체와 객체의 역할을 정의하는 것에 초점을 둔다.
객체 지향 프로그래밍
객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 Real world concepts을 Abstract를 통해 Software design entities로 프로그램하는 것이다.
우리의 실생활은 사람, 기기와 같은 각각의 객체로 이루어져 있다. 객체 지향 프로그밍은 실생활과 유사하게 프로그래밍한 것으로, 프로그램 구현에 필요한 객체와 각 객체의 역할을 정의하여 객체들 간의 상호작용을 통해 프로그램을 만드는 것을 말한다.
객체 지향 프로그래밍에는 많은 장점이 있다. 프로그램을 유연하고 변경이 용이하게 만들 수 있으며, 코드의 변경을 최소화하며 유지보수를 하는 데 유리하다. 참고로 Python, Java, C++은 객체지향 언어이다.
Class와 Instance
객체는 실제 세계에 존재하는 사물이나 개념 등을 표현한 것으로, 프로그래밍에서는 Class라는 프레임에서 만들어진 instance이다.
Class를 설계도라 보면, Instance는 설계도로 만든 집으로 비유할 수 있다. 각 집(Instance)들은 설계도(Class)를 참고하여 집을 짓는다. 혹은 Class를 차로 보면, Instance는 각 차 브랜드로 볼 수도 있다.
설계도 작성에도 규칙이 있듯이, Class 표기에도 규칙이 있다. 각각이 다른 표기를 사용한다면 함께 작업하는데 어려움이 있을 것이기에 규칙을 따라야 한다. 주로 UML(Unified Modeling Language)을 사용한다.
객체 지향 프로그래밍 특징
1. 캡슐화(Encapsulation)
캡슐화는 객체의 내부적 사항 (Data)에 대한 접근을 제한하며, 메서드(Behavior)를 통해 외부에서 접근하는 것이다. 캡슐화를 통해 클래스에 정의된 속성과 기능들을 보호할 수 있고(데이터 보호), 내부의 동작을 감추며 외부에는 필요한 부분만 노출할 수 있다(데이터 은닉).
실제 현업에서도 각 프로그래머가 작성한 코드의 노출과 변경을 최소화할 수 있기에, 코드에 오류가 있을 경우 어떤 프로그래머의 부분에 책임이 있는지도 확인 가능하다.
Python Example
class Car:
def __init__(self, make, model):
self._make = make # Encapsulated attribute
self._model = model # Encapsulated attribute
def drive(self):
print(f"Driving {self._make} {self._model}")
# Create a Car object
my_car = Car("Toyota", "Camry")
# Access encapsulated attribute indirectly through a method
my_car.drive() # Output: Driving Toyota Camry
make, model 속성은 Car 클래스 내에 캡슐화되었다. make, model 속성에 직접 액세스 하는 대신 drive() 메서드를 통해 간접적으로 액세스 한다.
2. 상속(Inheritance)
상속은 기존 클래스(상위클래스)의 특성을 기반으로 새로운 클래스(하위클래스)를 생성하는 것을 말한다. 상위 클래스로부터 만들어진 여러 개의 하위 클래스들 모두 상위 클래스의 속성과 기능들을 사용할 수 있기에, 간편하게 코드를 재사용할 수 있다. 또한 상속을 통해 새로운 클래스에서 기존 클래스의 기능을 확장하거나 변경할 수도 있다.
다중 상속은 한 클래스가 여러 개의 부모 클래스를 상속하는 것을 의미한다. Python은 다중 상속이 가능한 프로그래밍 언어이다. 참고로 Python에서는 만약 부모 노드에서 공통된 속성을 물려주고자 한다면, 처음에 명시된 부모 노드의 속성을 물려받는다.
Python Example
class Vehicle:
def __init__(self, make, model):
self.make = make
self.model = model
def display_info(self):
print(f"Make: {self.make}, Model: {self.model}")
class Car(Vehicle): # Car inherits from Vehicle
def __init__(self, make, model, color):
super().__init__(make, model)
self.color = color
def display_info(self): # Method overriding
print(f"Make: {self.make}, Model: {self.model}, Color: {self.color}")
# Create a Car object
my_car = Car("Toyota", "Camry", "Red")
# Access and display information
my_car.display_info() # Output: Make: Toyota, Model: Camry, Color: Red
Car 클래스(자식 클래스)는 Vehicle 클래스(부모 클래스)의 속성과 메서드를 상속받았다. 또한 'display_info()'는 Vehicle 클래스에도 존재하였는데, Car 클래스가 추가 정보(color)를 포함하여 메서드를 재정의하였다.
3. 다형성(Polymorphism)
다형성(多形性)은 어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질을 의미한다. 즉, 어떤 객체의 속성이나 기능이 그 맥락에 따라 다른 역할을 수행할 수 있는 특성이다. 예를 들어, 비행기라는 객체가 있을 때, 각각의 비행기는 이륙, 가속 등의 동작을 수행하지만, 이러한 동작들은 각 비행기마다 다르게 구현가능하다. 따라서, 같은 이름의 메서드가 각각의 비행기에서 다르게 구현되며 다형성을 구현가능하다.
다형성에는 메서드 오버라이딩과 메서드 오버로딩이 있다.
- 오버라이딩(Overriding): 부모 클래스에서 상속받은 메서드를, 자식 클래스에서 같은 이름을 사용 및 매개변수도 같되 새롭게 정의하는 것이다. 이를 통해 자식 클래스는 부모 클래스에서 상속받은 메서드를 자신에 맞게 변경 및 추가할 수 있다.
- 오버로딩(Overloading): 같은 이름의 메서드를 여러 개 정의한 후 매개변수의 타입, 개수, 순서 등을 다르게 하여 같은 이름을, 경우에 따라 호출하여 사용하는 것이다. 오버로딩을 통해 같은 이름의 메서드를 다양한 상황에서 사용할 수 있다.
Python Example
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self): # Method overriding
return "Woof!"
class Cat(Animal):
def speak(self): # Method overriding
return "Meow!"
# Function to demonstrate polymorphism
def make_sound(animal):
return animal.speak()
# Create Dog and Cat objects
my_dog = Dog()
my_cat = Cat()
# Call the make_sound function with different objects
print(make_sound(my_dog)) # Output: Woof!
print(make_sound(my_cat)) # Output: Meow!
Dog 및 Cat 클래스는 모두 Animal 클래스에서 상속되며 speak() 메서드를 재정의한다. make_sound() 함수는 다양한 유형의 Animal을 허용하고 특정 유형을 알 필요 없이 speak() 메서드를 호출하여 다형성을 보여준다.
4. 추상화(Abstraction)
추상화는 객체의 필수 속성과 메서드만 노출하고, 불필요한 구현 세부 정보는 숨기며, '어떻게 할지(how it's done)'가 아닌' 무엇을 하면 되는지(what to do)'에 초점을 맞춘 과정이다. 추상 클래스와 메서드는 하위 클래스가 따라야 할 방향성을 제공하며, 유연성과 확장성을 허용하는 동시에 일관된 동작을 보장한다.
Python Example
from abc import ABC, abstractmethod
class Shape(ABC): # Abstract class
@abstractmethod
def area(self):
pass
class Rectangle(Shape):
def __init__(self, length, width):
self.length = length
self.width = width
def area(self): # Implementation of abstract method
return self.length * self.width
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self): # Implementation of abstract method
return 3.14 * self.radius ** 2
# Create Rectangle and Circle objects
my_rectangle = Rectangle(5, 4)
my_circle = Circle(3)
# Call the area method for each object
print(my_rectangle.area()) # Output: 20
print(my_circle.area()) # Output: 28.26
Shape 클래스는 추상 메서드(@abstract method) area()를 갖는 추상 클래스이다. Rectangle 및 Circle과 같은 하위 클래스는 area() 메서드를 구현해야 한다.
Etc
- Object = Data + Behavior
- Data: field, member, variable, attribute
- Behavior: method, member function, operation
- self: reference variable pointing the instance itself
- super: reference variable pointing the base class instance
참고 문헌
데이터 구조 및 분석: Linear Structure and Dynamic Programming, 문일철 교수님, KOOC
GPT, Python Code
'공부 정리 > Computer' 카테고리의 다른 글
시뮬레이션(Simulation) (0) | 2024.02.15 |
---|