1. 상속
(1) 형식
class 클래스1 이름(상속할 클래스2 이름):
(2) 특징
1) 클래스1은 클래스2의 모든 멤버를 상속받으므로 클래스2의 모든 기능을 사용가능
2) 추가로 자기자신의 기능(고유 변수, 메소드 추가)도 사용 가능 - 클래스의 기능 확장
3) 기존 클래스가 라이브러리 형태로 제공되거나 수정이 허용되지 않는 상황에서 클래스를 변경하지 않고 기능을 추가하거나 기존 기능을 변경하려고 할 때 사용
(3) 메소드 오버라이딩(overriding 덮어쓰기): 부모 클래스에 있는 메서드를 동일한 이름으로 다시 만드는 것
1) 오버라이딩할 때는 꼭 부모의 변수를 사용할 필요는 없다. 처음에 데이터형을 정의하지 않기 때문에
# 클래스 상속연습
class Person:
say = '난 사람이야' #public
nai = 20
__kbs = '공용방송' # __변수명: private 현재 클래스에서만 참조 가능
def __init__(self, nai):
print('person생성자')
self.nai = nai #각각의 instance에서 달라질 수 있다고 뜻
def printInfo(self):
print('나이:{}, 이야기:{}'.format(self.nai, self.say))
def hello(self):
print('헬로우')
print('hello: ', self.say, self.__kbs)
pe = Person(22)
pe.printInfo()
pe.hello()
#자식클래스가 공통적으로 가질 멤버를 구성해 놓음
print()
#------------------------------------------------------------------------------------------------
print('Employee-------------------------------------------------------------')
print()
class Employee(Person):
say = '일하는 동물' # 자식과 동일한 멤버변수에 의해 부모의 say가 숨겨짐(은닉화)
subject = '근로자' #Employee 고유멤버
def __init__(self):
print('Employee생성자')
def printInfo(self): # 자식과 동일한 멤버메소드에 의해 부모의 메소드가 숨겨짐(은닉화)
print('Employee의 printInfo 메소드')
def empShow(self):
say = '수다떨기'
print(say) # '수달떨기' -> 없다면 모든 클래스 밖의 모듈의 say찾기. 그래도 없으면 error
print(self.say) # 현재 class의 say, 없으면 부모class의 say
print(super().say) # 무조건 부모 class의 say
self.printInfo() # 현재 class의 printInfo, 없으면 부모class의 printInfo
super().printInfo() # 무조건 부모 class의 printInfo
emp = Employee()
print(emp.say, emp.nai)
print(emp.subject)
emp.printInfo()
print()
emp.empShow()
print()
print('Worker-------------------------------------------------------------')
'''
class Worker(Person):
pass
wo = Worker(33)
print(wo.say, wo.nai)
wo.printInfo()
'''
class Worker(Person):
hobby = '코딩'
def __init__(self, nai):
print('Worker 생성자')
#나이를 받아서 부모에게 주고 싶다면
#자바는 자식의 생성자를 부르면 부모도 호출되는데 파이썬은 명시적으로 불러줘야 부모에게 할 수 있다.
super().__init__(nai) #bound method call
#== Person.__init__(self, nai) #unbound call 원형클래스의 이름으로 부른 것
def woShow(self):
self.printInfo()
super().printInfo()
wo = Worker(33)
wo.woShow()
print()
print('Programmer-------------------------------------------------------------')
class Programmer(Worker):
def __init__(self, nai):
print('Programmer 생성자')
Worker.__init__(self, nai)
def prShow(self):
self.printInfo()
super().printInfo()
#super().super()는 없음
def kbsShow(self):
print(self.__kbs)
pr = Programmer(35)
print(pr.say, pr.nai)
pr.hello()
pr.prShow()
# pr.kbsShow() error ∵ __kbs는 private라서
print('\n클래스 타입 확인-------------------')
a=3
print(type(a))
print(type(pr))
print()
#부모클래스 확인하기
print('부모클래스 확인하기---------------------')
print(Programmer.__bases__)
print(Worker.__bases__)
print(Person.__bases__)
2. 다중상속
예제1)
# 다중상속 - 순서가 중요(자바에서는 지원하지 않음)
print('어쩌구 저쩌구 하다가... 다중상속 필요')
class Tiger: # 최상위 클래스 Object를 상속받고 있는 거임
data = '호랑이 세상'
def cry(self):
print('호랑이 울부짖음')
def eat(self):
print('맹수는 고기를 먹음')
class Lion:
data = '사자세상'
def cry(self):
print('백수의 왕 으르렁')
def hobby(self):
print('사자의 취미는 낮잠')
class Liger(Tiger, Lion):
pass
aa = Liger()
aa.cry() # 먼저 적은 cry()가 출력됨. Tiger를 Lion보다 먼저 상속받는 괄호안에 적었으니 '호랑이 울부짖음'만 나옴
aa.eat()
print(aa.data)
aa.hobby()
print()
class Liger2(Lion, Tiger):
data = '라이거 멤버변수'
def play(self):
print('라이거2 고유메소드')
self.hobby()
super().hobby()
print(self.data)
print(super().data)
bb = Liger2()
bb.cry()
bb.eat()
bb.hobby()
print(bb.data)
print()
bb.play()
예제2)
class Animal:
def move(self):
pass #오버라이딩 해주길 기대, 강요는 아님. 자식클래스에서 오버라이딩을 강요하고 싶으면 추상메소드를 이용. 다형성 구사를 위해 오버라이딩 강요
class Dog(Animal):
name = '개'
def move(self):
print('개는 낮에 돌아다님')
class Cat(Animal):
name = '고양이'
def move(self):
print('고양이는 밤에 움직임')
print('눈빛이 빛남')
class Wolf(Dog, Cat):
pass
class Fox(Cat, Dog):
def move(self):
print('오버라이딩: 나는 여우라고 해')
def foxMethod(self):
print('여우 고유 메소드')
dog = Dog()
cat = Cat()
wolf = Wolf()
fox = Fox()
anis = [dog, cat, wolf, fox]
for a in anis:
a.move()
3. 추상클래스
(1) 추상 메소드를 가진 클래스
(2) 자식클래스에서 부모의 추상 메소드를 일반 메소드로 반드시 오버라이딩하게 하는 목적으로 사용
예제1)
예제2)
from abc import *
class Employee(metaclass = ABCMeta):
def __init__(self, irum, nai):
self.irum = irum
self.nai = nai
@abstractmethod
def pay(self):
pass
@abstractmethod
def data_print(self):
pass
def irumnai_print(self):
print('이름: '+ self.irum + ', 나이: '+ str(self.nai), end = ' ')
class Temporary(Employee):
def __init__(self, irum, nai, ilsu, ildang):
Employee.__init__(self, irum, nai) #irum과 nai를 가지고 부모에게 전달
self.ilsu = ilsu
self.ildang = ildang
def pay(self): #강요된 오버라이딩
return self.ilsu * self.ildang
def data_print(self): #강요된 오버라이딩
self.irumnai_print()
print(', 월급: '+ str(self.pay()))
# 클래스를 처음에는 pass로 해놓고 호출하는 방식을 먼저 보고 다음에 pass를 지우고 호출방식에 맞게 수행할 문장 작성
t = Temporary('홍길동',24,20,15000) #생성자를 부르면서 irum, nai, ilsu, ildang를 입력하니깐 Temporary클래스에도 이런 것을 다 받을 수 있는 생성자를 선언해야함
t.data_print()
#자식Temporary에게 저장된 '홍길동',24을 가져다가 부모클래스Employee의 irumnai_print가 가져다 씀
class Regular(Employee):
def __init__(self,irum, nai,salary):
super().__init__(irum, nai) # Regular의 super()는 Employee, super()를 쓸 때는 self를 매개변수로 가지면 안됨
self.salary = salary
def pay(self): #강요된 오버라이딩
return self.salary
def data_print(self): #강요된 오버라이딩
self.irumnai_print()
print(', 급여: ' + str(self.pay()))
r = Regular('한국인',27,3500000)
r.data_print()
class SalaryMan(Regular):
def __init__(self, irum, nai, salary, sales, commission):
super().__init__(irum, nai,salary)
self.sales = sales
self.commission = commission
def pay(self): # 일반메소드를 오버라이딩
return super().pay() + int(self.sales * self.commission)
def data_print(self): # 일반메소드를 오버라이딩
self.irumnai_print()
print(', 수령액: ' + str(self.pay()))
"""def data_print(self):
self.irumnai_print()
print(', 수령액: ' + str(super().pay() + int(self.sales * self.commission)))"""
s = SalaryMan('손오공', 29, 1200000, 5000000, 0.25)
s.data_print()
예제2의 관계)
4. 클래스변수
(1) 클래스 내에서 선언된 변수
(2) 객체변수와 다르게 클래스로 만든 모든 객체에 공유된다.
(3) Z클래스의 객체가 a, b일 때 Z클래스의 클래스변수가 변경되면 a.클래스변수와 b.클래스변수가 모두 변경된다.
=> 모두 같은 메모리 주소를 공유하기 때문
8. 사용자 입력과 출력 (0) | 2021.04.29 |
---|---|
9. 파일 읽고 쓰기 File I/O (0) | 2021.04.25 |
7-1. 클래스 (0) | 2021.04.25 |
6. 모듈(module) (0) | 2021.04.25 |
5. 함수 (0) | 2021.04.25 |