Python/파이선과 친해지기

[Python] - Python과 매우 친해지기-클래스의 상속

아 한 2억만 상속받고 싶다

- 리덕토 - 

 

Python과 매우 친해지기 그 3번째 시간은 클래스의 상속(Inherit)이다. 상속은 객체지향에서 빼놓을 수 없는 중요한 기능이고, 약간의 이해도가 필요하기에 별도의 포스팅을 작성하였다.


상속(Inherit)의 정의와 사용

우리의 친구 위키백과에서 상속이 무엇인지 정의를 가져와 보자

객체 지향 프로그래밍(OOP)에서, 상속(inheritance)은 객체들 간의 관계를 구축하는 방법이다

- 출처 : 위키백과(ko.wikipedia.org/wiki/%EC%83%81%EC%86%8D_(%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D))

으흠; 조금 모호한 부분이 있는 거 같다. 객체들 간의 관계를 상속만으로 구축되는 것은 아니지만; 위키가 필자보다 몇만 배는 똑똑하기 때문에 쟤가 저러면 그런 거다. 정의는 저렇고 상속은 "다른 객체로부터 새로운 객체를 재생성하는 것"으로 이해해주면 될 거 같다. 

 

이런 상황을 가정하자 우리는 객체 지향 프로그램의 방식으로 프로그램을 만들고 있는 도중인데, 요리사와 소방관의 클래스를 만들어야 된다. 둘은 사람이라는 기본 전제를 가지고 있다. 따라서 사람으로 가질 수 있는 모든 속성이나 공통된 행동이 있을 것이다. 상속은 이러한 아이디어를 정확하게 표현해준다.

여기서 상속을 하는 클래스를 부모(Parent) 클래스라고 하며, 상속을 받는 Fire Fighter이나 Cook을 자식(Sub) 클래스, 같은 레벨에서 상속을 받은 Fire Fighter와 Cook은 서로를 형제(Sibling) 클래스라고 지칭한다. 이렇게 실행한 상속은 다음과 같은 특징을 가진다.

 

1. 자식은 부모의 클래스 변수, 매서드에 접근할 수 있다.
2. 부모는 자식의 클래스변수, 메서드에 접근할 수 없다.
3. 여러 개의 부모를 상속받을 수 있다.(여기서 다이아몬드형 상속이라는 문제가 발생한다. 궁금한 인원은 더보기를 확인)
더보기

위와 같은 형태가 다이아몬드 상속이다. 물론 상속받은 객체를 상속받는 것은 문제가 되지 않으나, Fire Fighter가 human에게 상속받은 some_function()와 Cook이 human에게 상속받은 some_function() 중 GoodMan이 사용해야 하는 매서드가 무엇인지 정할 수 없는 문재가 발생한다.

 

상속은 오로지 조금 더 구체적인 자식으로 단방향으로만 진행된다. 아래의 코드를 확인하면서 Python에서 상속의 사용법을 익혀보자

class human :
    
    name = ""

    def __init__(self,name) :
        self.name = name

    def introduce(self) :
        print("hello im human "+self.name)

    def job(self) :
        print("I have no jobs")


class firefighter(human) :      ## firefighter은 human을 상속받음

    def __init__(self,name) :
        super().__init__(name)  ## 부모의 생성자를 호출

    def job(self) :             ## job은 firefighter가 오버라이딩
        print("my job is firefighter")

    def new_introduce(self) :
        super().introduce()     ## super를 이용, 부모의 매서드 호출
    
    def extinguish(self) :
        print("you off fire!")

        
if __name__ == "__main__" :

    cheolsu = human("cheolsu")
    younghee = firefighter("younghee")

    cheolsu.introduce()
    cheolsu.job()

    younghee.extinguish()
    younghee.introduce()        ## 부모의 매서드인 introduce사용가능
    younghee.job()
    
    

우선 human 클래스는 우리가 저번 시간에서 모두 배운 내용으로 이루어져 있다.(생성자, 매머드의 정의, 클래스 변수 name 등) 제일 먼저 눈에 띄는 것은 상속을 할 때 class [클래스명](상속받을 클래스명) :으로 정의한 점이다.(여러 개를 상속받으려 먼 상속받을 클래스명을 콤마로 나누어 적어주면 된다.)

 

프로그램의 main을 보면 human객체 cheosufirefighter객체 younghee가 있다. 주석에 적어두었듯 younghee 또한 부모의 매서드인 introduce를 사용하고 있다.

 

자식에서 부모를 호출할 때는 앞에 super()를 붙이는데 super() 매더스는 자신의 부모를 반환한다. 따라서 younghee의 super(). introduce()는 human.introduce()로 해석되며, firefighter 생성자의 super().__init__(name)은 부모 생성자를 호출하는 것과 같다.

 

오버 라이딩(Overriding)

부모에서 정의된 메서드를 자식에서 재정의하는 것을 오버 라이딩(Overriding)이라고 한다. 코드에서는 human에서 정의된 job 함수가 firefighter에서 재정의되며 오버 라이딩(Overriding)된 것을 확인할 수 있다.

* 혹시 다른 언어에서 넘어와서 오버 로딩(Overloading)의 개념을 찾으시는 분이 계시다면 아쉽게도 Python은 오버 로딩을 허용하지 않는다는 비보를 전한다. 단, Pythoin은 파라미터를 받을 수 있는 방법을 상당히 다양하게 제공한다.)


이번 시간에는 클래스와 상속에 대해서 알아보았다. 어떤가, 이제 객체 지향과 클래스에 대해서 조금은 익숙해 느낌이 드는가? 다음 시간에는 우리의 프로그램을 조금 더 안정적으로 만들 수 있는 예외처리에 대해서 알아보도록 하자