36. 클래스 상속

Joy·2020년 4월 2일
0

클래스 상속

물려받은 기능을 유지한채로 다른 기능을 추가할 때 사용하는 기능

  • 기반 클래스(base class): 기능을 물려주는 클래스, 부모 클래스(parent class), 슈퍼 클래스(superclass)
  • 파생 클래스(derived class): 상속을 받아 새롭게 만드는 클래스, 자식 클래스(child class), 서브 클래스(subclass)
class 기반클래스이름:
    코드
class 파생클래스이름(기반클래스이름):
    코드

기반 클래스의 능력을 그대로 활용하면서 새로운 클래스를 만들 때 사용
기존 기능을 재사용할 수 있어서 효율적

사람클래스로 학생클래스 만들기

class Person:
    def greeting(self):
        print('안녕하세요.')
 
class Student(Person):
    def study(self):
        print('공부하기')
 
james = Student()
james.greeting()    # 안녕하세요.: 기반 클래스 Person의 메서드 호출
james.study()       # 공부하기: 파생 클래스 Student에 추가한 study 메서드

상속관계 확인 : issubclass 함수를 사용

클래스가 기반 클래스의 파생 클래스인지 확인
기반 클래스의 파생 클래스가 맞으면 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().메서드()
    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()는 사용하지 않아도 됨

메서드 오버라이딩 overriding

파생 클래스에서 기반 클래스의 메서드를 새로 정의 - 기반 클래스의 메서드를 무시하고 새로운 메서드를 만든다
어떤 기능이 같은 메서드 이름으로 계속 사용되어야 할 때 메서드 오버라이딩을 활용
예)

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입니다.

메서드 탐색 순서(Method Resolution Order, MRO)

다이아몬드 상속에 대한 해결책

  • 클래스.mro()
>>> D.mro()
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

D의 메서드 호출 순서는 자기 자신 D, 그 다음이 B. 따라서 D로 인스턴스를 만들고 greeting을 호출하면 B의 greeting이 호출

추상클래스 abstract class

메서드의 목록만 가진 클래스이며 상속받는 클래스에서 메서드 구현을 강제하기 위해 사용

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))
profile
roundy

0개의 댓글