2025-01-20T02:26:20
This commit is contained in:
133
doc/10_04_inheritance.md
Normal file
133
doc/10_04_inheritance.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# 상속 (Inheritance)
|
||||
상속은 기존 클래스(부모 클래스)의 속성과 메소드를 그대로 물려받아 새로운 클래스(자식 클래스)를 생성하는 것을 의미합니다. 이를 통해 코드 재사용성을 높이고, 계층적인 클래스 구조를 만들 수 있습니다.
|
||||
|
||||
```python
|
||||
class Animal:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def sound(self):
|
||||
print("소리를 냅니다.")
|
||||
|
||||
class Dog(Animal):
|
||||
def sound(self):
|
||||
print("멍멍")
|
||||
|
||||
class Cat(Animal):
|
||||
def sound(self):
|
||||
print("야옹")
|
||||
```
|
||||
위 예시에서 Dog 클래스와 Cat 클래스는 Animal 클래스를 상속받아 name 속성과 sound 메서드를 물려받습니다. 동물의 공통적인 특징은 Animal 클래스에서 정의하고, 각 동물의 특징은 자식 클래스에서 오버라이딩하여 구현합니다.
|
||||
|
||||
## 다형성 (Polymorphism)
|
||||
다형성은 같은 메시지에 대해 서로 다른 객체가 다르게 반응하는 것을 의미합니다. 상속을 통해 구현되며, 하나의 변수나 참조로 다양한 타입의 객체를 가리킬 수 있게 해줍니다.
|
||||
|
||||
## 추상 클래스 (Abstract Class)
|
||||
추상 클래스는 일부 또는 모든 메서드가 구현되지 않은 클래스입니다. 즉, 추상 클래스는 자체적으로 객체를 생성할 수 없으며, 다른 클래스의 상위 클래스로 사용되어 하위 클래스에서 구체적인 기능을 구현하도록 강제합니다. 추상 클래스는 공통적인 속성과 메서드를 정의하여 코드의 재사용성을 높이고, 클래스 간의 관계를 명확하게 나타내는 데 사용됩니다.
|
||||
|
||||
* 추상 메서드: 구현이 생략된 메서드로, 자식 클래스에서 반드시 구현해야 합니다. abc 모듈의 `@abstractmethod` 데코레이터를 사용하여 선언합니다.
|
||||
* 일반 메서드: 구체적인 구현이 있는 메서드로, 자식 클래스에서 오버라이딩하거나 그대로 사용할 수 있습니다.
|
||||
|
||||
```python
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class Animal(ABC):
|
||||
@abstractmethod
|
||||
def sound(self):
|
||||
pass
|
||||
|
||||
class Dog(Animal):
|
||||
def sound(self):
|
||||
print("멍멍")
|
||||
|
||||
class Cat(Animal):
|
||||
def sound(self):
|
||||
print("야옹")
|
||||
```
|
||||
위 예시에서 Animal 클래스는 sound 메서드를 추상 메서드로 선언하여, Dog 클래스와 Cat 클래스에서 반드시 sound 메서드를 구현하도록 강제합니다.
|
||||
|
||||
## 인터페이스
|
||||
인터페이스는 클래스가 갖춰야 할 메서드의 집합을 정의한 것입니다. 즉, 인터페이스는 클래스가 어떤 기능을 제공해야 하는지에 대한 규약을 정의하는 역할을 합니다. 파이썬에서는 인터페이스라는 개념이 명시적으로 존재하지 않지만, 추상 클래스를 이용하여 인터페이스와 유사하게 사용할 수 있습니다.
|
||||
|
||||
```python
|
||||
class IPerson():
|
||||
@abstractmethod
|
||||
def hello(self):
|
||||
pass
|
||||
|
||||
class Person(IPerson):
|
||||
def hello(self):
|
||||
print("Hello")
|
||||
```
|
||||
|
||||
## 다중 상속
|
||||
다중 상속이란, 하나의 클래스가 두 개 이상의 부모 클래스로부터 속성과 메서드를 상속받는 것을 의미합니다. 이를 통해 더욱 복잡하고 다양한 기능을 가진 클래스를 만들 수 있습니다.
|
||||
### 장점
|
||||
* 코드 재사용성 증가: 여러 클래스에 공통적으로 사용되는 기능을 하나의 부모 클래스에 정의하고, 이를 여러 자식 클래스에서 상속받아 사용할 수 있습니다.
|
||||
* 유연성 향상: 다양한 특성을 가진 클래스를 조합하여 새로운 클래스를 만들 수 있습니다.
|
||||
### 단점
|
||||
* 복잡성 증가: 클래스 간의 관계가 복잡해져 코드를 이해하기 어려울 수 있습니다.
|
||||
* 모호성: 여러 부모 클래스에 동일한 이름의 메서드가 있을 경우, 어떤 메서드가 호출될지 명확하지 않을 수 있습니다. 이를 해결하기 위해 MRO(Method Resolution Order)가 사용됩니다.
|
||||
* 다이아몬드 문제: 여러 상속 경로를 통해 같은 조상 클래스에 도달할 경우 발생하는 문제입니다.
|
||||
|
||||
```python
|
||||
class Flyer:
|
||||
def fly(self):
|
||||
print("날아다닙니다.")
|
||||
|
||||
class Swimmer:
|
||||
def swim(self):
|
||||
print("헤엄칩니다.")
|
||||
|
||||
class FlyingFish(Flyer, Swimmer):
|
||||
pass
|
||||
|
||||
fish = FlyingFish()
|
||||
fish.fly() # 날아다닙니다.
|
||||
fish.swim() # 헤엄칩니다.
|
||||
```
|
||||
위 예시에서 FlyingFish 클래스는 Flyer와 Swimmer 두 클래스를 상속받아 날 수 있고 헤엄칠 수 있는 기능을 모두 가지게 됩니다.
|
||||
|
||||
### MRO(Method Resolution Order)
|
||||
MRO(Method Resolution Order)는 파이썬에서 다중 상속 시 메서드 호출 순서를 결정하는 규칙입니다. 즉, 어떤 클래스의 메서드를 호출할 때, 파이썬 인터프리터가 어떤 순서로 상위 클래스들을 검색하여 메서드를 찾는지를 정의합니다.
|
||||
|
||||
#### 파이썬의 MRO 알고리즘: C3 알고리즘
|
||||
파이썬은 C3 알고리즘이라는 복잡한 알고리즘을 사용하여 MRO를 계산합니다. 이 알고리즘은 다음과 같은 조건을 만족하는 MRO를 생성합니다.
|
||||
|
||||
* 선형화: MRO는 선형 순서를 가지며, 각 클래스는 한 번만 나타납니다.
|
||||
* 상속 관계 유지: 부모 클래스는 항상 자식 클래스보다 먼저 나타납니다.
|
||||
* 깊이 우선 검색: 왼쪽에서 오른쪽으로 깊이 우선 검색을 수행합니다.
|
||||
|
||||
```python
|
||||
class A: pass
|
||||
class B(A): pass
|
||||
class C(A): pass
|
||||
class D(B, C): pass
|
||||
|
||||
print(D.__mro__)
|
||||
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
|
||||
```
|
||||
D 클래스의 MRO는 D -> B -> C -> A -> object 순으로 구성됩니다. 즉, D 클래스의 메서드를 호출할 때, 먼저 D 클래스 내에서 메서드를 찾고, 없으면 B 클래스, C 클래스, A 클래스 순으로 검색합니다.
|
||||
|
||||
super() 함수는 MRO를 따라 다음에 검색해야 할 클래스의 메서드를 호출하는 데 사용됩니다.
|
||||
|
||||
```python
|
||||
class A:
|
||||
def foo(self):
|
||||
print("A")
|
||||
|
||||
class B(A):
|
||||
def foo(self):
|
||||
print("B")
|
||||
super().foo()
|
||||
|
||||
class C(B):
|
||||
def foo(self):
|
||||
print("C")
|
||||
super().foo()
|
||||
|
||||
c = C()
|
||||
c.foo() # 출력: C B A
|
||||
```
|
||||
위 예시에서 super() 함수는 현재 클래스의 MRO에서 다음 클래스의 메서드를 호출합니다.
|
||||
|
||||
Reference in New Issue
Block a user