Python

Python 문법 기초 26 - class 상속(self 와 super)

코딩탕탕 2022. 10. 22. 17:08

 

# 클래스의 상속 : 다형성을 구사 가능

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이다.