본문 바로가기
Programming/Python

25. 상속(Inheritance)

by IT learning 2021. 3. 28.
728x90

오늘은 클래스 기반의 객체 지향 언어들이 지원하는 기능인 상속에 대해 공부해보겠다.

상속이라는 기능은 매우 고급 기술이고, 객체 지향에서 제일 중요하다고 여기는 기술 중 하나이다.

 

이번에는 너무 딥하게 파지 않고, 간단한 예시를 보며 공부해보겠다.

 

정말 딥하게 파고 싶다면, C++을 이용하여 공부하는 것을 추천한다.

(필자는 C++부터 시작했다)

 

상속

상속이란, 다른 누군가가 만들어 놓은 기본 형태에 내가 원하는 것만 교체하는 것이 상속이다.

음.. 그러니까 엄마에게서 태어난 아들이 엄마가 가지고 있는 특징들을 가지고 태어나는 느낌이라고 보면 된다. (Ex. 돈도 가능하다)

 

다중 상속

다중 상속이란, 아까 위에서 설명한 것으로 얘기해보자면, 이번엔 엄마의 특징 뿐만 아니라, 부모님 전체의 특징을 다중으로 가지고 태어난 아들이라고 생각하면 될듯 하다.

 

단일이 아닌 다중으로 상속을 받은 느낌이다.

 

프로그래밍 언어는 기반이 되는 것을 부모라고 부르고, 이를 기반으로 생성하는 것을 자식이라고 부른다.

부모가 자식에게 자신의 기반을 물려주는 기능이므로 '상속'이라고 부르는 것이다.

 

우리는 상속만 살펴볼것이다.

추후에 기회가 된다면 C++을 이용하여 상속에 대해 자세히 알아보겠다.

# 상속의 활용
class Parent:
    def __init__(self):
        self.value = "테스트"
        print("Parent 클래스의 __init()__ 메소드가 호출되었습니다.")
    def test(self):
        print("Parent 클래스의 test() 메소드 입니다.")
        
class Child(Parent):
    def __init__(self):
        Parent.__init__(self)
        print("Child 클래스의 __init__ 메소드가 호출되었습니다.")
        
child = Child()
child.test()
print(child.value)

위 코드를 살펴보자.

두개의 클래스가 존재한다.

하나는 Parent 클래스, 하나는 Child 클래스다. 두 클래스의 가장 큰 특징이라면,  Child 클래스는 Parent클래스를 상속받은 채로 선언되어있다.

이렇게 되면, Child클래스에서 Parent의 함수와 변수들을 사용할 수가 있다.

위 코드의 실행결과이다.

Child 클래스의 코드를 살펴보자.

생성자 내부에 코드를 보면, 먼저 Parent의 생성자를 불러왔다. 그래서 먼저 Parent 클래스의 메소드가 호출되었다.

다음 줄, Child 클래스를 호출한다는 출력을 내보내는 구조이다.

 

실행하는 칸에도 child를 이용하여 test()를 실행했다.

Parent 를 상속받았기 때문에 사용이 가능하다.

 

그리고 마지막 child.value 는 상속받은 것이기 때문에 사용이 가능하다.

 

간단하게 생각하자. 단순히 다른 클래스에 있는 걸 사용할 수 있게 하는 기능이라고.

 

예외 클래스 만들기

상속은 기존에 있는 클래스를 기반으로 조금 수정해서 내가 원하는 클래스를 만들 때 사용한다.

그럼 Exception이라는 기존에 있는 클래스를 조금 수정해서 CustomException이라는 클래스를 만들어보겠다.

# 사용제 정의 예외 클래스 만들기
class CustomException(Exception):
    def __init__(self):
        Exception.__init__(self)
        
raise CustomException

위 코드의 실행결과이다.

Exception 클래스를 상속했으므로, Exception 클래스와 이름만 다르지 모두 같은 클래스이다.

따라서 rasie로 예외를 발생시키는 것도 가능하다.

 

조금 수정을 해보겠다.

# 자식 클래스로써 부모의 함수 재정의(오버라이드) 하기
class CustomException(Exception):
    def __init__(self):
        Exception.__init__(self)
        print("#### 내가 만든 오류가 생성되었습니다. ####")
    def __str__(self):
        return "오류가 발생했습니다."
    
raise CustomException

일단 __init__() 내부에서 간단한 출력을 해보게 하고, __str__() 함수를 만들어 원하는 형태로 수정한다.

위 코드의 실행결과이다.

참고로 __str__() 함수는 Exception 클래스에도 정의되어 있다.

이처럼 부모 클래스에 정의되어 있는 함수를 자식에서 다시 정의하는 것재정의 또는 오버라이드(Override)라고 부른다.

 

코드를 실행해보면 출력이 약간 바뀌는것을 볼 수 있다.

 

추가로 기존에 있던 함수/변수 이외에 것을 완전히 새로 정의하는 것도 가능하다.

# 자식 클래스로써 부모에 없는 새로운 함수 정의하기

class CustomException(Exception):
    def __init__(self, message, value):
        Exception.__init__(self)
        self.message = message
        self.value = value
        
    def __str__(self):
        return "오류가 발생했습니다."
    
    def print(self):
        print("#### 오류정보 ####")
        print("메시지:", self.message)
        print("값:", self.value)
        
try:
    raise CustomException("딱히 이유없음", 273)
except CustomException as e :
    e.print()

이렇게 Exception 클래스에 있는 것들을 바꿔보았다.

위 코드의 실행결과이다.

이렇게 출력이 되고, 내가 바꾼 값들이 출력되는 것을 볼 수있다.

이렇게 오버라이드를 통해 부모에게서 받은 것들을 내가 원하는 대로 수정 할 수 있다.

 

오버라이드와 오버로드를 같다고 생각하면 안된다!

오버로드는 같은 이름의 함수이지만 기능과 매개변수의 형태가 다른 것을 의미하고

오버라이드는 위에서 배운 상속을 받은 것을 내가 원하는 것으로 수정할 수 있는걸 의미한다.

 

이렇게만 알아도 객체 지향에서 알아야 할 기본들은 숙지했다고 볼 수 있다.

위 개념들은 이전에 배운 프라이빗 변수, 게터 세터와 같이 모든 객체 지향 언어에서 사용하는 개념들이다.

 

이번에 개념을 제대로 알고 간다면, 다른 언어를 배울때 선언하는 방법만 다르지, 개념은 같다라는 것이다.

 

숙지하기 바란다!

 

오늘은 상속에 대해 공부했다.

 

이로써 필자가 공부했던 '혼자 공부하는 파이썬' 책을 다 보았다.

파이썬의 기초적인 부분을 훑어 볼수 있어서 좋았고, 파이썬으로 머신러닝과 딥러닝을 배워볼 예정이다.

 

머신러닝 딥러닝 공부 상황도 블로그에 올릴 예정이다.

728x90

댓글

IT_learning's Commit