Week01 Day04

 

OOP(Object-Oriented Programming)

객체 지향 프로그래밍(영어: Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍의 패러다임 중 하나이다.

컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 “객체“들의 모임으로 파악하고자 하는 것이다.
각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.1

프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.2

OOP에서 클래스와 객체라는 개념이 등장한다.

클래스(class)는 객체 지향 프로그래밍(OOP)에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀이다.
객체를 정의 하기 위한 상태(멤버변수)와 메서드(함수)로 구성된다.3

객체는 클래스에서 정의한 것을 토대로 실제 메모리상에 할당된 것을 의미한다.2

클래스와 객체에 대한 비유로는 클래스는 붕어빵 만드는 기계이고 객체는 붕어빵이다.
만약 붕어빵 기계에 속 재료를 팥을 넣으면 팥 붕어빵이 되고 슈크림이 들어가면 슈크림 붕어빵이 된다.

# Person class는 country(국적)이라는 값을 받아서 객체를 생성한다.
class Person:
  def __init__(self, country):
    self.country = country
  def __str__(self):
    return f"I`m from {self.country}"

# Person class에 "korea"를 입력하면 "korea" 라는 특성을 가진 객체가 생성된다.
# 또한 "japan"을 입력하면 "japan"이라는 특성을 가진 객체가 생성된다.
# 그리고 Person에 의해 생성된 korean, janpanese 객체는 메모리에 할당된다.
korean = Person("korea")
print(korean) # I`m from korea
janpanese = Person("japan")
print(janpanese) # I`m from japan

그럼 클래스는 메모리에 할당되지 않느냐? 라는 질문을 받는다면 클래스 역시 메모리에 할당된다.
나는 단지 클래스에 의해 생성된 것을 객체라고 하는 것을 강조하고 싶었다.

OOP 특징

  • 추상화(abstract) asd

  • 상속(inheritance)
    A 클래스가 B 클래스를 상속받으면 B 클래스의 메소드와 변수를 사용할 수 있다.
    이때 B를 부모, A를 자식 클래스라 한다.
    상속을 받는 이유는 부모 클래스와 비슷한 클래스를 만들고 싶은데 모든 코드를 복사하여 일부만 수정하는 경우를 피하기 위함이다.
    즉, 기존 클래스를 재활용하여 확장하기 위함이다.

# Vehicle class는 탈 것을 나타내는 클래스이다.
class Vehicle:
  def __init__(self, driver):
    self.driver = driver
  def __str__(self):
    return f"{self.driver} is driver."

# Bus class는 탈 것 중 버스를 추상화한 클래스이다.
# Vehicle의 메소드와 변수를 동일하게 Bus class에서 정의하지 않고 상속하여 코드를 재활용했다.  
# 현실에서의 Bus를 추상화한 class이며 버스가 움직이는 것을 구현하기 위해 "move"라는 메소드를 추가했다.
# 결과적으로 상속을 함으로써 코드의 중복을 피하고 기존 class에 변수 혹은 메소드를 추가하여 확장할 수 있다.
class Bus(Vehicle):
  def __init__(self, driver):
    super().__init__(driver)
  def move(self):
    ...
    return

다음은 상속을 받을 때 고려했던 사항에 대한 비유이다.

soldier class와 gun class가 있다.
gun을 가지고 있는 soldier를 구현하고 싶을 때 gun class를 상속받아야 할까?
만약 상속받는 다면 gun-soldier class가 될 것이다.
하지만 soldier의 다른 무기 class를 고려해야 한다면 어떻게 해야 될까?
예를 들어 sword class, shield class를 모두 가진 soldier class를 구현해야 한다면 gun-soldier class에서 어떻게 해야 될까?
이럴때는 상속하는게 좋지 않고 soldier class 내 무기 class의 객체를 만들어서 사용하면 편리할 것이다.
gun-soldier class는 gun에 특화된(?) class이므로 gun에 대해 세부적으로 구현할 수 있을 것이며 sword와 shield를 함께 구현하는 것은 적절하지 않을 것이다.

  • 캡슐화 ㅁㄴㅇ

  • 다형성(polymorphism)
    프로그램 언어의 다형성(多形性, polymorphism; 폴리모피즘)은 그 프로그래밍 언어의 자료형 체계의 성질을 나타내는 것으로, 프로그램 언어의 각 요소들(상수, 변수, 식, 오브젝트, 함수, 메소드 등)이 다양한 자료형(type)에 속하는 것이 허가되는 성질을 가리킨다. 반댓말은 단형성(monomorphism)으로, 프로그램 언어의 각 요소가 한가지 형태만 가지는 성질을 가리킨다.

위키피디아 정의를 보며 이해하기 힘들었지만 예시를 보고 어느정도 이해했다.

단형성 체계를 가진 프로그램 언어에서는 함수는 각각 한가지 의미로 식별되는 이름과 결합되어 있어 다른 동작을 구현하기 위해서는 다른 이름을 써야 한다.
예를 들어 어떤 값을 문자열 형식으로 변환하는 단순한 경우를 생각해보자.
단형성 형태 체계를 가지지 못한 언어에서는, 다음과 같이 개별 함수로 되어 있을 것이다.
string = StringFromNumber(number); //숫자를 문자열로 바꾸는 경우
string = StringFromDate(date); //날짜를 문자열로 바꾸는 경우

한편 다형성 체계를 가진 언어에서는, StringValue와 같은 범용 메소드 이름을 정의하여 형태에 따라 각각 적절한 변환 방식을 정의해둠으로써 객체의 종류와 상관없는 추상도가 높은 변환 형식을 구현할 수 있다.
string = number.StringValue(); //숫자를 문자열로 바꾸는 경우
string = date.StringValue(); //날짜를 문자열로 바꾸는 경우

# Vehicle class를 상속받은 Bus와 Airplane class 각각에서 run 메소드를 다시 구현했다.
class Vehicle:
  def run():
    print("출발합니다")
class Bus(Vehicle):
  def run():
    print("Bus 출발힙니다")
class Airplane(Vehicle):
  def run():
    print("비행기 이륙합니다")

다형성은 overriding과 관련이 있다.
overriding은 부모 클래스로부터 상속받은 메소드를 자식 클래스에서 자유롭게 구현을 새롭게 정의하는 성질이다.