Python 문법 기초 26 - class 상속(self 와 super)
# 클래스의 상속 : 다형성을 구사 가능
class Animal:
def __init__(self):
print('Animal 생성자')
def move(self):
print('움직이는 생물')
class Dog(Animal): # 상속
def __init__(self):
print('Dog 생성자')
def my(self):
print('난 댕댕이')
dog1 = Dog()
dog1.move()
dog1.my()
class Horse(Animal):
pass
horse1 = Horse()
horse1.move()
<console>
Dog 생성자
움직이는 생물
난 댕댕이
Animal 생성자
움직이는 생물
Dog ()안에 부모 클래스를 넣으면 상속된다.
dog1을 호출하면 Animal 메소드를 호출할 수 있다.
dog1을 호출하면 생성자가 호출되는데 생성자가 없으면 부모 클래스인 Animal 의 생성자가 호출된다.
생성자가 있으면 Dog의 생성자를 호출한다.
파이썬에서는 java처럼 오버로드가 존재하지 않는다. 그러므로 같은 메소드명은 사용할 수 없다.
Animal은 다른 파일로 만들어 두고 import 하는 것이 정석이다.
# 클래스의 상속
class Person:
say = '난 사람~'
nai = '22'
def __init__(self, nai):
print('Person 생성자')
self.nai = nai # Person 객체의 nai 와 기억장소가 다르다.
def printInfo(self):
print('나이:{}, 이야기:{}'.format(self.nai, self.say))
def hello(self):
print('안녕')
print(Person.say, Person.nai)
# Person.printInfo() err () 안에 아무것도 넣어주지 않았기때문에
p = Person('24') # 객체를 생성할 때 nai가 주어지며 다른 주소를 가지고 있다.
p.printInfo()
p.hello()
<console>
난 사람~ 22
Person 생성자
나이:24, 이야기:난 사람~
안녕
객체를 생성할 때 nai가 주어지며 기존 nai 와는 다른 주소를 가지고 있다.
자식 클래스에 생성자가 없는 경우
print('***' * 10)
class Employee(Person):
pass
emp = Employee('25') // 부모클래스 생성자 호출
emp.printInfo()
<console>
Person 생성자
나이:25, 이야기:난 사람~
Employee 를 호출했지만 생성자가 없다. 그러므로 부모 클래스인 Person의 생성자를 호출한다. Person의 생성자에는 필수 매개변수 값으로 nai가 들어가는데 부모클래스를 호출한 것이므로 nai의 값을 넣어주면 된다.
자식 클래스에 생성자가 있는 경우
class Employee(Person):
def __init__(self):
print('Employee 생성자')
# emp = Employee('26')
emp = Employee()
emp.printInfo()
<console>
err
Employee 생성자
나이:22, 이야기:난 사람~
Employee의 생성자가 존재하므로 Employee의 생성자가 실행되는데 매개변수 값으로 26을 부여했기 때문에 err가 발생했다. 그 이유는 Employee의 생성자에는 매개변수가 없기 때문이다.
매개변수 값을 부여하지 않으면 부모 클래스를 호출하는데 self.nai는 비어있는 값이기 때문에 Person의 nai를 호출하게 된다.
class Employee(Person):
say = '일하는 동물'
subject = '근로자'
def __init__(self):
print('Employee 생성자')
def printInfo(self):
print('Employee의 printInfo 메소드')
def empPrintInfo(self):
print(self.say, self.nai, self.subject)
print(self.say, super().say) # 부모 클래스의 say
self.printInfo()
super().printInfo() # 부모 클래스의 printInfo
emp = Employee()
emp.printInfo()
emp.empPrintInfo()
<console>
Employee 생성자
Employee의 printInfo 메소드
일하는 동물 22 근로자
일하는 동물 난 사람~
Employee의 printInfo 메소드
나이:22, 이야기:일하는 동물
부모 클래스와 자식 클래스의 메소드가 동일하면 호출한 클래스의 변수를 우선시 한다.
empPrintInfo를 호출하면 self.say, self.nai의 값은 부모클래스에서 가져오게 된다.
만약 empPrintInfo에 변수가 존재하면 그 변수 값을 가져오게 된다.
super(). 을 사용하면 현재 클래스는 pass 하고 부모클래스의 say를 찾게 된다.
class Person:
say = '난 사람~'
nai = '22'
__kbs = '공영방송' # private 멤버 변수
def __init__(self, nai):
print('Person 생성자')
self.nai = nai # Person 객체의 nai 와 기억장소가 다르다.
def printInfo(self):
print('나이:{}, 이야기:{}'.format(self.nai, self.say))
def hello(self):
print('안녕')
__를 사용하면 private 멤버 변수로서 해당 클래스에서만 사용 가능하다. 상속은 불가능하다.
class Worker(Person):
def __init__(self, nai):
print('Worker 생성자')
super().__init__(nai) # 부모 생성자 호출
# super()가 nai를 가지고 부모 생성자에게 간다.
def wPrintInfo(self):
self.printInfo()
wor = Worker('28')
print(wor.say, wor.nai)
wor.wPrintInfo()
<console>
Worker 생성자
Person 생성자
난 사람~ 28
나이:28, 이야기:난 사람~
class Programmer(Worker):
def __init__(self, nai):
print('Programmer 생성자')
# super().__init__(nai) # Bound call
Worker.__init__(self, nai) # UnBound call
def ProShow(self):
self.printInfo()
pr = Programmer('29')
print(pr.say, pr.nai)
pr.ProShow()
<console>
Programmer 생성자
Worker 생성자
Person 생성자
난 사람~ 29
나이:29, 이야기:난 사람~
Programmer에서 직접 Person으로 갈 수는 없다. 부모인 Worker를 거처야 된다.
print(type(3))
print(type(pr))
print(type(wor))
print(Programmer.__bases__, Worker.__bases__, Person.__bases__)
<console>
<class 'int'>
<class '__main__.Programmer'>
<class '__main__.Worker'>
(<class '__main__.Worker'>,) (<class '__main__.Person'>,) (<class 'object'>,)
__bases__는 조상 클래스를 명시하는 함수이다.
모든 class의 조상은 object class이다.