4. 상속
상속은 기존에 존재하는 class로부터 코드와 데이터를 이어받고 필요한 기능을 추가하는 방법이다.
가령 Vehicle이란 부모클래스가 존재했으며 그 내부에 마력, 바퀴수 등의 공통된 field, method가 존재했다고 가정하자. 그런데 Car, Truck, Bus 등 세부화된 자식클래스에선 기존 부모클래스의 field, method를 고스란히 유지하면서 세부적 기능을 추가해야만 한다. 가령 Truck은 최대적재화물이라던가 Bus은 최대탑승인원 등이 있다. 이럴 경우 부모클래스로부터 기존 기능을 고스란히 이어받되, 새로운 기능을 추가하는 것이 바로 상속인 것이다.
따라서 상속은 객체지향 프로그램이의 "is-a" 관계를 구축함에 있어 핵심이다.
class Vehicle:
def __init__(self, makr, model, color, price):
self.makr = makr
self.model = model
self.color = color
self.price = price
def setmakr(self, makr):
self.makr = makr
def getmakr(self):
return self.makr
def getDesc(self):
return str(self.makr)...
class Truck(Vehicle):
def __init__(self, makr, model, color, price, payload):
super().__init__(makr, model, color, price)
self.payload = payload
def setPayload(self, payload):
self.payload = payload
def getPayload(self):
return self.payload
가령 이 경우 Truck이라는 자식클래스가 인수로 부모클래스인 Vehicle을 우선적으로 받고, __init__ 내부에 부모클래스(super())의 __init__을 그대로 가져오는 것을 확인할 수 있다. 거기에 추가하고 싶은 instance field인 payload를 부차적으로 할당하는 것이다.
def main():
mine = Truck("Tesla", "Model S", "white", 10000, 2000)
mine.setMakr("Hyundai")
mine.setPayload(20000)
print(mine.getDesc())
main()
이와 같이 Truck class를 활용할 수 있다.
class Car:
def __init__(self, speed):
self.__speed = speed
def set_speed(self, speed):
self.__speed = speed
def getDesc(self):
return "차량=("+str(self.__speed)+")"
class Sportscar(Car):
def __init__(self, speed, turbo):
super().__init__(speed)
self.__turbo = turbo
#이하 method 생략
obj = SportsCar(100, True)
#Turbo 기능을 True/False로 on/off할 수 있다. 이경우엔 True, 100으로 on
print(obj.getDesc())
obj.setTurbo(False) #Turbo 기능을 off하여 해당 instance를 없앤 case
class Shape:
def __init__(self, x, y):
self.x = x
self.y = y
def area(self):
print("계산불가")
def perimeter(self):
print("계산불가")
class Rec(Shape):
def __init__(self, x, y, w, h):
super().__init__(x, y)
self.w = w
self.h = h
def area(self):
return self.w*self.h
def perimeter(self):
return 2 * (self.w + self.h)
r = Rec(0,0,100,200)
print("사각형 면적:",r.area())
print("사각형 둘레:",r.perimeter())
class Person:
def __init__(self, name, code):
self.name = name
self.code = code
#이하생략
class Prof(Person):
def __init__(self, name, code):
super().__init__(name, code)
self.teach = []
self.pay = 10000
def assignTeach(self, teach):
self.teach.append(teach)
def __str__(self):
return #이하생략
class Student(Person):
UNDERGRADUATE = 0
POSTGRADUATE = 1
def __init__(self, name, code, studentType):
super().__init__(name, code)
self.studentType = studentType
self.lec = []
self.cgpa = 0
def enrolllec(self, lec):
self.lec.append(lec)
#이하생략
kim = Student("김서강", "20182018", Student.UNDERGRADUATE)
kim.enrolllec("자료구조")
print(kim)
park = Prof("박선배", "19701970")
park.assignteach
5. Method Overriding
class BankAccount:
def __init__(self,name, number, balance):
self.balance = balance
self.name = name
self.number = number
def withdraw(self, amount):
self.balance -= amount
return self.balance
def deposit(self, amount):
self.balance += amount
return self.balance
class SavingsAccount(BankAccount):
def __init__(self, name, number, balance, interest):
super().__init__(name, number, balance)
self.interest = interest
def add_interest(self):
self.balance += self.balance * self.interest
class CheckingAccount(BankAccount):
def __init__(self, name, number, balance):
super().__init__(name, number, balance)
self.withdraw = 10000 #수표발행 수수료
def withraw(self, amount):
return BankAccount.withdraw(self, amount + self.withdraw)
a1 = SavingsAccount("김서강", 123456, 10000, 0.05)
a1.add_interest()
print("저축예금의 잔액=",a1.balance)
a2 = CheckingAccount("김철수",123457, 20000000)
a2.withdraw(100000)
print("당좌예금의 잔애=", a2.balance)
Method를 Override한다는 것은 단어 그대로의 역할을 한다. 우선 부모클래스의 Method를 자식클래스에서 불러온다. 위 경우 CheckingAccount에서 BankAccount의 withdraw를 불러왔다. 자식클래스의 withdraw는 부모클래스의 기능을 그대로 반환하는 것에 그친다. 그러나 그 인수가 amount + self.withdraw로 수표발행 수수료인 10000을 감안한 잔고를 값으로 반환하는 것이다.
class Employee:
def __init__(self, name, salary):
self.salary = salary
self.name = name
def getSalary(self):
return self.salary
class Manager(Employee):
def __init__(self, name, salary, bonus):
super().__init__(name, salary)
self.bonus = bonus
def getSalary(self):
salary = super().getSalary()
return salary + self.bonus
def __repr__(self):
return "이름: {}, 월급: {}, 보너스: {}".format(self.name, self.salary, self.bonus)
kim = Manager("김서강", 2000000, 100000)
print(kim)
마찬가지로 Employee의 getSalary를 Override한 예제다. 자식클래스에서 getSalary를 override해주었는데 이 때 salary를 그대로 받아오고 이에 self.bonus를 추가하여 재정의해주었다. Manager는 Salary+Bonus까지 수령하니까 getSalary 함수의 반환값이 재정의된 것을 확인할 수 있다.
6. Method Overloading
Overloading | Overriding | |
Method Name | same | same |
input variable & type | different | same |
return type | doesn't matter | same |
class Vehicle:
def __init__(self, name):
self.name = name
def drive(self):
return "unknown"
def stop(self):
return "unknown"
class Truck(Vehicle):
def drive(self):
return "트럭을 운전합니다"
def stop(self):
return "트럭을 정지합니다"
class Car(Vehicle):
def drive(self):
return "승용차를 운전합니다"
def stop(self):
return "승용차를 정지합니다"
cars = [Truck('red'), Truck('blue'), Car('yellow')]
for car in cars:
print(car.name + ":" + car.drive())
위 예시와 같이 Vehicle일 때는 추상적인 method가 Truck과 Car 자식클래스로 넘어오면서 구체화된 것을 확인할 수 있다.
7. Class 포함 관계
참고로 모든 Class의 상위클래스는 Object Class인데, 이 Class 내부의 Method가 __init__, __repr__이 내장된 것이다. 보통 부모클래스 생성시 Class명 옆의 괄호를 생략하는데 Object가 생략된 것이다.
여지껏 우리는 Class를 통해 'is - a'의 상속 관계를 살펴보았다. 위 예시와 같이 "자동차는 운송수단이다"처럼 자동차가 운송수단이란 포괄적 개념 속에 들어가는 것을 의미한다.
이제부터 Class간의 관계인 'has - a'를 살펴본다. 이는 특정 class가 다른 class를 내포하는 경우라고 판단할 수 있다. 상속의 개념과 같이 한 class가 다른 class를 포함하는 것은 아니지만 '가지는' 형식이다.
class Card:
symb = ['club','dia','hart', 'spade']
rank = ['1','2','3','4','5','6','7','8','9','10','K','J','Q']
def __init__(self, symb, rank):
self.symb = symb
self.rank = rank
def __str__(self):
return Card.symb[self.symb]+" "+Card.rank[self.rank]
class Deck:
def __init__(self):
self.cards = []
for symb in range(4):
for rank in range(13):
card = Card(symb, rank)
self.cards.append(card)
def __str__(self):
lst = [str(card) for card in self.cards]
return str(lst)
deck = Deck()
print(deck)
위 예제에서 핵심적인 부분은 Card(symb, rank)를 Deck 내부에서 호출한 것이다. 이를 통해 Card의 __init__이 실행되어 self.symb = symb, self.rank = rank가 Deck Class 내부에 종속되었다. Card의 반환값이 Card.symb와 Card.rank가 결합된 형태며 이는 card 변수로 저장된다.
'프로그래밍언어 > python' 카테고리의 다른 글
[파이썬] openpyxl & selenium 활용법 (0) | 2022.02.08 |
---|---|
[파이썬문법] 12. Threading(1) (0) | 2022.01.21 |
[파이썬문법] 11. Class(1) (0) | 2022.01.15 |
[파이썬문법] 9. 반복문 (0) | 2021.12.15 |
[파이썬문법] 8. iterable variables (0) | 2021.12.15 |