# 상속과 오버라이딩

 

1. 상속

 

상속은 사전적 정의에 따르면 부모나 친족적 관계에 있는 사람의 유산을 물려 받는 제도입니다. 클래스에서의 상속은 부모의 유산을 자식이 물려 받듯이 부모 클래스의 멤버와 메소드를 자식 클래스가 물려받을 수 있습니다. 이런 경우는 흔히 있습니다. 예를 들어 라이브러리를 제작할 때 특정 자료구조를 만들어서 모든 클래스가 이 자료구조를 이용하게 하고 싶다면 클래스의 상속을 이용하게 하면 됩니다.  추가적으로 파이썬에서 기본 제공되는 자료형 또한 클래스이기 때문에 자신만의 독특한 자료형을 만들 수 도 있겠죠.

 

상속을 이해하고자 할 때 가장 쉬운방법은 기존의 클래스를 이용하되, 내가 원하는 멤버와 메소드를 추가하는 것으로 이해 하는 것입니다.

 

클래스의 상속

먼저 총이라는 간단한 클래스가 있다고 가정해 보겠습니다. 클래스라는 것은 유형, 무형으로 존재하는 어떤 것을 코드로 나타내는 것입니다.  그러면 총(Rifle)이라는 객체는 파괴력, 탄창, 현재 남은 총알 등의 속성을 가지고 있을 테고, 기능으로는 장전이나 발사가 있을 수 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Rifle:
    def __init__(self,Mag, atk):
        self.__Mag = Mag
        self.__leftMag = Mag
        self.__atk = atk
    
    @property
    def Mag(self):
         return self.__Mag
    
    @property
    def leftMag(self):
        return self.__leftMag
    
    @leftMag.setter
    def leftMag(self, num):
        self.__leftMag = num
    
    @property
    def atk(self):
        return self.__atk
    
    @atk.setter
    def atk(self,num):
        self.__atk = num
        
    def Reload(self):
        self.__leftMag = self.__Mag
        
    def Shoot(self):
        if self.__leftMag:
            self.__leftMag -= 1
        else:
            print("장전하세요")
cs

 

이 클래스는 Rifle입니다. 제가 앞서 언급한 대로 생성자에 탄창, 남은 총알, 파괴력등의 요소를 만들었습니다. 또한 상속을위해 각 클래스멤버의 property와 setter를 작성하여 직접 멤버변수에는 접근하지 못하지만, 메소드를 통하여 가능하게 구현하였습니다. 탄창(Mag)은 처음 인스턴스 생성 이후 오염을 방지하기위해 setter에서 제외했습니다. Rifle클래스의 메소드로는 총이 실제로 가지고있는 기능인 발사(Shoot), 장전(Reload) 등을 포함 시켰습니다. 같은 클래스 안에서는 property나 setter를 이용하여 멤버에 접근할 필요가 없기때문에 직접접근하는 방식으로 구현하였습니다.(장전과 발사에 있는 self.__leftMag)

 

만약 총이라는 클래스를 상속받아 저격총이라는 클래스를 만들고자 하면 총이 가지고 있는 속성은 그대로 유지할 것입니다. 하지만 총이라는 클래스에는 망원경이라는 요소가 없기 때문에 속성을 하나 추가하고 망원경 조준이라는 기능을 추가해야겠죠.  그런 의미에서 멤버 변수에 Zoom을 추가하였고 메소드로는 increaseAtk을 넣어 Zoom과 파괴력을 곱해 다시 파괴력에 저장하는 코드를 작성하였습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ScopeRifle(Rifle):
    def __init__(self,Mag,atk):
        super().__init__(Mag,atk)
        self.__Zoom = 1
    
    @property
    def Zoom(self):
        return self.__Zoom
    
    @Zoom.setter
    def Zoom(self,num):
        self.__Zoom *= num
    
    def increaseAtk(self):
        self.atk *= self.__Zoom
cs

 

__init__을 보면 super().__init__이라는 구문이 있습니다. 이는 부모클래스의 생성자 때문에 필요한 구문입니다. 생성자 규칙에 따라 부모클래스는 탄창과 파괴력이라는 멤버를 필요로 합니다. 이 멤버를 채워주지 않으면 에러가 발생합니다. 

아래의 코드를 실행시키고 각각의 메소드를 테스트 해보겠습니다.

 

1
2
rifle = Rifle(5,10)
sniper = ScopeRifle(5,10)
cs

 

 

Rifle 클래스에 정의되어 있는 내용은 잘 동작하는 것을 확인하였습니다.  rifle을 상속받은 sniper도 잘 동작하는 것을 확인 할 수 있습니다. 

이번에는 sniper클래스의 고유 기능을 테스트 해보도록 하겠습니다.

 

 

제가 의도한 대로 잘 동작하고 있습니다.  atk는 부모클래스의 멤버이면서 property지만 setter를 같이 작성했기 때문에 sniper에서 접근하고 같을 변경시킬 수 있었습니다. public 하게 구현하면 사실 이런 고생은 안해도 됩니다. 하지만 객체지향 프로그래밍에서는 getter setter를 제외하고는 클래스 멤버에대한 외부 클래스의 접근을 금하고 있기때문에 property 설정을 꼭 하셔야 합니다.

 

 


 

 

2. 오버라이딩

 

총과 저격총 사이에는 명확하지 않지만 가끔씩  상속받은 클래스가 부모의 기능을 똑같이 가지고 있지만 구현 방법이 다를 때가 존재합니다. 이런 경우에는 같은 이름의 메소드를 작성하고 다른 기능을 수행하게 해야합니다. 예를 들어 산탄총의 경우를 생각해보겠습니다. 일반 총은 발사당 1개의 총알이 소비되지만 산탄총은 3발이 나간다고 칩시다. 산탄총도Shoot이라는 메소드가 당연히 필요하지만 부모 클래스의 Shoot과 다르게 동작해야 되겠죠? 파이썬에서는 부모 클래스의 메소드와 같은 이름의 메소드를 자식 클래스에 작성하여 부모 클래스의 메소드를 덮어버리는 방법이 있습니다. 이를 우리는 오버라이딩이라고 합니다.

 

1
2
3
4
5
6
7
class ShotGun(Rifle):
    def __init__(self,Mag,atk):
        super().__init__(Mag,atk)
    
    def Shoot(self):
        if self.leftMag:
            self.leftMag -= 3
cs

 

위의 코드는 Rifle클래스를 상속받아 만든 ShotGun클래스입니다.  ShotGun은 Rifle과 모든게 같지만 발사당 3개의 총알이 소비된다고 했었죠? 그 내용을 Shoot이라는 메소드를 정의하고 그 안에 구현하면 됩니다.

부모 클래스에 Shoot이라는 메소드가 있다고 하더라도 오버라이딩을 통해 이를 덮어 쓸 수 있습니다. 실제로 이 코드가 잘 작동하는지 확인 해보겠습니다.

 

 

코드가 정상적으로 작동하는 것을 확인 할 수 있습니다. 상속을 받을 때는 이런 식으로 기능을 고려해서 메소드를 다시 설계 해야할 필요가 있는 경우도 있습니다.

# 파이썬 제어문



제어문이란 프로그래밍 언어에서 실행순서를 변경시키거나 또는 조건에 따라 실행해야 할 명령문을 제어하는데에 사용되는 구문입니다. 일반적으로 프로그램은 위에서 아래로 순차적으로 실행되지만, 어떤 조건에 대해서만 실행해야 하는 경우나 특정 부분을 반복하여 실행해야 하는 경우 등이 있습니다.

python에서는 if, for, while문을 사용하여 흐름을 제어할 수 있습니다.



1. while 문


특정작업을 반복하여 실행해야 할 경우 반복문을 사용하면 간단히 해결할 수 있습니다. while문은 반복문의 일종으로 조건문이 참일 경우 반복을 계속합니다. 


1
2
3
while 조건:
    수행할 작업
    ...
cs


while이라는 키워드를 먼저 적고 그 뒤에 조건을 적어주면 됩니다. 앞선  if문 강의에서 배웠던 비교, 논리연산자가 쓰일 수 있습니다.


2. while 문 사용예제


glass라는 변수의 값을 0으로 초기화 하고 while문의 조건으로 glass가 10보다 작을 경우를 설정합니다. 이렇게 하면 while문의 조건이 참이니 동작을 시작하겠죠? 하지만 glass 의 값을 while문 안에서 늘려주지 않는다면 while은 무한히 실행될 것입니다. 고로 glass의 값을 +=을 통해 1씩 늘려주기로 하겠습니다. 또 while 문안에 print문을 넣어 한잔 마셨습니다. 를 출력해 보도록 하겠습니다. 그리고 glass의 값이 10이 되었을 때 취했으니 집에 돌아가요. 라는 문구를 출력해보도록 하겠습니다.



1
2
3
4
5
6
7
8
glass = 0
#10번 반복
while glass < 10:
    glass+=1
    print("한잔 마셨습니다.")
    if glass == 10:
        print("취했으니 집에 돌아가요.")
    
cs




3. while문 이스케이프(escape)


while문은 조건문이 참인 동안 계속해서 하위 구문을 반복적으로 실행합니다. 하지만 중간에 while문을 빠져나가고 싶을 경우에는 break문을 넣어 즉시 while문을 빠져나갈 수 있습니다.


1
2
3
4
5
6
7
8
9
number = 77
counter = 2
while counter < number:
    if number%counter == 0:
        print("소수가 아닙니다.")
        break
    counter += 1
    if counter == number
        print("소수 입니다.")
cs


'Dev > python' 카테고리의 다른 글

[python] 제어문(if, for, while) - 3  (0) 2019.03.23
[python] 시퀀스 자료형과 이터러블  (1) 2019.03.23
[python] 제어문(if, for, while) - 1  (0) 2019.02.15
[python] 튜플과 Immutable  (0) 2019.02.14
[python] 딕셔너리(dictionary)  (0) 2019.02.13

+ Recent posts