물려받은 기능을 유지한채로 다른 기능을 추가할 때 사용하는 기능
class 기반클래스이름: 코드 class 파생클래스이름(기반클래스이름): 코드
기반 클래스의 능력을 그대로 활용하면서 새로운 클래스를 만들 때 사용
기존 기능을 재사용할 수 있어서 효율적
class Person:
def greeting(self):
print('안녕하세요.')
class Student(Person):
def study(self):
print('공부하기')
james = Student()
james.greeting() # 안녕하세요.: 기반 클래스 Person의 메서드 호출
james.study() # 공부하기: 파생 클래스 Student에 추가한 study 메서드
클래스가 기반 클래스의 파생 클래스인지 확인
기반 클래스의 파생 클래스가 맞으면 True, 아니면 False를 반환
>>> class Person:
... pass
...
>>> class Student(Person):
... pass
...
>>> issubclass(Student, Person)
True
Student가 Person의 파생 클래스이므로 issubclass는 True
상속관계 (is-a 관계): 상속은 명확하게 같은 종류이며 동등한 관계일 때 사용
예) person - student
포함관계(has-a 관계): 속성에 인스턴스를 넣는 포함 방식을 사용
예) person을 관리하는 personlist 클래스(리스트 속성에 Person 인스턴스를 넣어서 관리-상속을 사용하지 않고 속성에 인스턴스를 넣어서 관리하므로 PersonList가 Person을 포함)
예)
class Person:
def __init__(self):
print('Person __init__')
self.hello = '안녕하세요.'
class Student(Person):
def __init__(self):
print('Student __init__')
self.school = '파이썬 코딩 도장'
james = Student() #student class에 인스턴스 james
print(james.school) #'Student __init__'만 출력
print(james.hello) # 기반 클래스의 속성을 출력하려고 하면 에러가 발생함
person class에 hello 속성.
person class 상속받는 student class.
student class에 인스턴스 james 만들고 hello에 접근하면 에러 - 기반 클래스 Person의 init 메서드가 호출되지 않았기 때문
- super().메서드()
super()를 사용해서 기반 클래스의 init 메서드를 호출
class Person:
def __init__(self):
print('Person __init__')
self.hello = '안녕하세요.'
class Student(Person):
def __init__(self):
print('Student __init__')
super().__init__() # super()로 기반 클래스의 __init__ 메서드 호출
self.school = '파이썬 코딩 도장'
james = Student()
print(james.school)
print(james.hello)
super().init()와 같이 기반 클래스 Person의 init 메서드를 호출해주면 기반 클래스가 초기화되어서 속성이 만들어짐 > 기반 클래스 Person의 속성인 hello가 잘 출력
!! 만약 파생 클래스에서 init 메서드를 생략한다면 기반 클래스의 init이 자동으로 호출되므로 super()는 사용하지 않아도 됨
파생 클래스에서 기반 클래스의 메서드를 새로 정의 - 기반 클래스의 메서드를 무시하고 새로운 메서드를 만든다
어떤 기능이 같은 메서드 이름으로 계속 사용되어야 할 때 메서드 오버라이딩을 활용
예)
class Person:
def greeting(self):
print('안녕하세요.')
class Student(Person):
def greeting(self):
print('안녕하세요. 저는 파이썬 코딩 도장 학생입니다.')
james = Student()
james.greeting() #결과: 안녕하세요. 저는 파이썬 코딩 도장 학생입니다.
greeting 메서드가 person에도 student에도 있음.
class Person:
def greeting(self):
print('안녕하세요.')
class Student(Person):
def greeting(self):
super().greeting() # 기반 클래스의 메서드 호출하여 중복을 줄임
print('저는 파이썬 코딩 도장 학생입니다.')
james = Student()
james.greeting()
결과: 안녕하세요.
저는 파이썬 코딩 도장 학생입니다.
여러 기반 클래스로부터 상속을 받아서 파생 클래스를 만드는 방법
class 기반클래스이름1: 코드 class 기반클래스이름2: 코드 class 파생클래스이름(기반클래스이름1, 기반클래스이름2): 코드
예) 사람, 대학교 클래스를 상속받는 대학생
def greeting(self):
print('안녕하세요. A입니다.')
class B(A):
def greeting(self):
print('안녕하세요. B입니다.')
class C(A):
def greeting(self):
print('안녕하세요. C입니다.')
class D(B, C):
pass
x = D()
x.greeting() # 안녕하세요. B입니다.
다이아몬드 상속에 대한 해결책
- 클래스.mro()
>>> D.mro()
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
D의 메서드 호출 순서는 자기 자신 D, 그 다음이 B. 따라서 D로 인스턴스를 만들고 greeting을 호출하면 B의 greeting이 호출
메서드의 목록만 가진 클래스이며 상속받는 클래스에서 메서드 구현을 강제하기 위해 사용
from abc import * class 추상클래스이름(metaclass=ABCMeta): @abstractmethod def 메서드이름(self): 코드
abc모듈 가져와서 클래스 활호안에 meta=지중. 메스드 만들때 위에 @붙여서 추상메서드
추상 클래스를 상속받았다면 @abstractmethod가 붙은 추상 메서드를 모두 구현해야 함
추상 클래스는 파생 클래스가 반드시 구현해야 하는 메서드를 정해주기
추상 클래스는 인스턴스로 만들 수가 없다 -그래서 지금까지 추상 메서드를 만들 때 pass만 넣어서 빈 메서드로 만든 것 (호출할일 없으니까)
다음 소스 코드에서 동물 클래스 Animal과 날개 클래스 Wing을 상속받아 새 클래스 Bird를 작성하여 '먹다', '파닥거리다', '날다', True, True가 각 줄에 출력되게 만드세요.
class Animal:
def eat(self):
print('먹다')
class Wing:
def flap(self):
print('파닥거리다')
class Bird(Animal, Wing):
def fly(self):
print('날다')
b = Bird()
b.eat()
b.flap()
b.fly()
print(issubclass(Bird, Animal))
print(issubclass(Bird, Wing))