# 클래스 상속은 다음과 같이 클래스를 만들 때 ()를 붙이고 안에 부모 클래스 이름을 붙인다.
# class 부모클래스이름:
# 코드
#
# class 자식클래스이름(부모클래스이름):
# 코드
# 사람 클래스를 만들고 이를 상속받는 학생 클래스를 만들어보자.
classPerson:defgreeting(self):print('안녕하세요')classStudent(Person):defstudy(self):print('공부하기')james=Student()james.greeting()# 안녕하세요. 부모 클래스 Person의 greeting 호출
james.study()# 공부하기. 자식 클래스 Student의 study 호출
# 이러한 상속 관계를 확인하고 싶을 때는 issubclass 함수를 사용하면 된다.
# 이 함수는 어떤 클래스가 부모 클래스의 자식 클래스인지 확인한다.
print(issubclass(Student,Person))# Student는 Person의 자식 클래스이므로 True
상속 관계와 포함 관계 알아보기
# IS-A 관계: 동등한 관계를 말한다.
# 예로, 학생은 사람이다. 처럼 말했을때 말이 된다면 IS-A 관계이다.
classPerson:defgreeting(self):print('안녕하세요.')classStudent(Person):defstudy(self):print('공부하기')# 동등 관계가 아니라 사람 목록을 관리하는 등의 포함 관계를 갖는 클래스를 만든다면
# 리스트 속성에 Person 인스턴스를 넣어서 관리하면 된다.
classPersonList:def__init__(self):self.person_list=[]# 리스트에 Person 인스턴스를 넣어서 관리
defappend_person(self,person):# 리스트 속성에 Person 인스턴스를 추가하는 메소드
self.person_list.append(person)
기반 클래스의 속성 사용하기
# 자식 클래스의 __init__에서는 super()를 사용해서 __init__ 메소드를 호출해줘야 한다.
# 그렇지 않으면 부모 클래스에 있는 속성이 만들어지지 않아 접근이 불가능하기 때문이다.
classPerson:def__init__(self):print('Person __init__')self.a='aaa'classStudent(Person):def__init__(self):print('Student __init__')super().__init__()# 부모 클래스의 __init__ 메소드 호출
self.b='bbb'james=Student()# Student __init__ Person __init__
print(james.b)# bbb
print(james.a)# aaa
# 만약 자식 클래스에서 __init__ 메소드를 생략한다면 부모 클래스의 __init__ 이 자동으로 호출되므로
# super()는 사용할 필요가 없다.
메소드 오버라이딩 사용하기
# 이번에는 자식 클래스에서 부모 클래스의 메소드를 새로 정의하는 메소드 오버라이딩에 대해 알아보자.
# 아래와 같이 부모 클래스와 자식 클래스에 같은 메소드를 만들어보면,
classAAA:deffoo(self):print('AAA')classBBB:deffoo(self):# super().foo() # 이렇게 상위 클래스의 메소드를 호출하는 것도 가능하다.
print('BBB')obj=BBB()obj.foo()# BBB가 출력된다. 부모 클래스의 foo를 무시하고 자식 클래스의 foo를 호출한다.
# 이렇게 상위 클래스의 메소드를 무시하는 하위 클래스의 메소드를 만드는 것을 메소드 오버라이딩 이라고 한다.
다중 상속 사용하기
# 다중 상속은 여러 부모 클래스로부터 상속을 받아 자식 클래스를 만드는 방법이다.
# 클래스를 만들 때 괄호 안에 클래스 이름을 , 로 구분해서 넣어주면 된다.
classAAA:defaaa(self):print('AAA')classBBB:defbbb(self):print('BBB')classCCC(AAA,BBB):defccc(self):print('CCC')# 이렇게 해서 만든 CCC 클래스는 AAA와 BBB 클래스를 모두 상속받았다.
# 그렇기 때문에 AAA, BBB 클래스의 aaa, bbb 메소드를 모두 사용 가능하다.
obj=CCC()obj.aaa()# AAA
obj.bbb()# BBB
obj.ccc()# CCC
# 그런데 이 때, AAA 클래스와 BBB 클래스가 둘 다 foo() 메소드를 갖고 있다면
# CCC는 어떤 클래스의 foo()를 호출해야 할까?
# 클래스이름.mro() 를 통해서 메소드 탐색 순서를 확인할 수 있다.
print(CCC.mro())# [<class '__main__.CCC'>, <class '__main__.AAA'>, <class '__main__.BBB'>, <class 'object'>]
# 즉, 상속 클래스 목록에서 왼쪽에 있는 것부터 탐색을 한다.
추상 클래스 사용하기
fromabcimport*# 파이썬은 추상 클래스라는 기능을 제공한다.
# 추상 클래스는 메소드의 목록만 가진 클래스이며 상속받는 클래스에서 메소드 구현을 강제하기 위해 사용한다.
# 만약 한 클래스라도 구현이 되어있지 않다면 에러가 발생한다.
# 추상 클래스를 만들려면 abc(abstract base class) 모듈을 import 해야한다.
# 그리고 클래스의 () 안에 metaclass=ABCMeta를 지정하고,
# 메소드를 만들 때 위에 @abstractmethod 를 붙여서 추상 메소드로 지정한다.
# 학생 추상 클래스 StudentBase를 만들고 이 추상 클래스를 상속받아 Student 클래스를 만들어보자.
classStudentBase(metaclass=ABCMeta):@abstractmethoddefstudy(self):pass@abstractmethoddefgo_to_school(self):passclassStudent(StudentBase):defstudy(self):print('공부하기')defgo_to_school(self):print('학교가기')std=Student()std.study()# 공부하기
std.go_to_school()# 학교가기
# 이처럼 추상 클래스는 상속받는 클래스가 반드시 구현해야 하는 메소드를 정해줄 수 있다.
# 추상 클래스는 인스턴스를 만들기 위한 목적이 아니므로 추상 클래스로 인스턴스를 만들려고 하면 에러가 발생한다.
# 즉, 오로지 상속에만 추상 클래스를 사용한다.
Leave a comment