본문으로 바로가기

Python: Class04

category Programming/Python 2021. 1. 27. 17:27
반응형

지금까지 파이썬의 클래스를 주제로 3개의 글을 포스팅하였다. 그리고 그 과정에서 객체나 메소드, 접근 제한자 등... 클래스와 관련된 여러 내용을 살펴보았다.
파이썬이 스크립트 언어라는 포지션을 갖고 있다보니, 가볍게 사용할 수 있는 동적 프로그래밍 언어 정도로만 인식하는 경향이 있다. 이쯤에서 눈치챘겠지만, 파이썬은 철저히 객체지향 프로그래밍 언어를 표방하고 있다. 그리고 오늘 다룰 주제는 객체지향의 꽃이라 할 수 있는 상속에 관한 내용을 이야기하려 한다.

프로그래밍 언어에 경험이 적은 사람에게 상속이라는 단어를 이야기하면, 막장 드라마의 단골 소재로 등장하는 유산 상속을 먼저 떠올릴 것이다. 지금 이야기하는 이 상속과 막장 드라마에 나오는 유산 상속의 그 상속은 같은 의미를 가진 단어이다. '프로그래밍에서 뜬금 없이 왠 상속?' 이라고 생각할 수 있다. 나도 처음엔 그랬으니까...
보통 상속이라는 단어는 부모가 자식에게 재산 등을 물려주는 의미를 담고있다. 객체지향에서 상속 역시 누군가에게 무엇인가물려주는 것을 의미한다. 여기서 말하는 누군가란 '클래스가 다른 클래스에게'이고, 무엇인가는 '멤버 변수와 속성, 그리고 메소드'이다.

상속에 대한 간단한 예를 위 그림에서 확인할 수 있다. 그림의 예제 프로그램에는 clsParent라는 클래스와 clsChild라는 클래스가 정의되어 있다. 일단 두 클래스를 정의하는 1번과 9번 라인을 비교해보자. clsParent 뒤에 따라오는 괄호 안은 비어있지만, clsChild 뒤에 따라오는 괄호 안에는 clsParent가 지정되어 있다. 파이썬에서는 한 클래스가 다른 클래스의 내용을 상속 받을 때, 이렇게 클래스 이름 뒤에 따라오는 괄호 안에 상속 받을 클래스의 이름을 넣어준다. 그래서, clsChild 클래스 내부는 pass 말고 다른 내용이 없지만, clsParent 클래스에 정의된 내용과 동일한 작업을 clsChild 객체를 통해 수행할 수 있는 것이다.

이렇게 상속이라는 과정을 거치게 되면, 한 클래스가 가지고 있던 속성이 다른 클래스에 고스란히 전달된다. 그래서, 상속되는 클래스를 Base 클래스, 상속 받는 클래스를 Derived 클래스라고 부른다. 그리고, 우리가 살고 있는 인간 세상에서 부모가 자신의 유산을 자식에게 물려주는 것과 비유하여, 상속되는 클래스를 부모 클래스, 상속 받는 클래스를 자식 클래스라고 부르기도 한다.

이번에는 처음 예제 프로그램에서 clsChild 내부에 생성자 메소드와 get 메소드를 하나 정의하였다. 처음 예제에서 clsChild는 pass 처리되었지만, clsParent 클래스의 내용을 상속 받았으므로, 객체의 생성 및 get 메소드를 호출해서 사용할 수 있었다. 이것을 바꿔 말하면, 부모 클래스의 생성자 메소드까지도 모두 상속 받아서 사용했다는 의미이다.
그런데, 위 예제에서는 자식 클래스인 clsChild에 별도의 생성자 메소드가 정의되었다. 다시 말해, 상속 받은 부모 클래스의 생성자 메소드를 자식 클래스가 뒤집어 엎었다(?)는 의미다. 뒤집어 엎었다는 표현이 좀 거칠다면, 재정의 (redefine)라는 표현으로 바꿔 써도 관계 없다. 어찌 되었든, 상속 관계에서 자식 클래스는 부모 클래스의 유산을 재정의 할 수 있다. 이것을 Method Overriding 이라고 한다.
자식이 부모로부터 상속 받은 재산을 유용하게 사용하기 위해 낡은 건물을 수리하거나, 물려 받은 땅 위에 건물을 세우는 등의 행동을 한다고 해서 문제가 되는 것은 아니다. 마찬가지로, 자식 클래스가 반드시 부모 클래스에 종속적인 관계일 필요는 없다. 메소드 오버라이딩도 이런 관점에서 바라본다면 쉽게 이해할 수 있다. 부모로부터 물려 받은 메소드 중에서 나와 맞지 않는 메소드에 대해서는 오버라이딩 해서 재정의 할 수 있다는 의미이다. 이것을 좀 더 연장해서 생각한다면, 부모 클래스에는 없었던 메소드를 새로 추가하는 것도 얼마든지 가능해진다. 위 그림의 AnotherVar 메소드처럼 말이다.

이렇게 두 클래스를 상속 관계로 정의하는 경우, 자식 클래스는 부모 클래스의 내용을 마음대로 불러다 쓸 수 있고, 심지어는 메소드의 내용을 재정의 할 수 있으며, 없었던 내용을 추가할 수도 있다. 하지만, 부모 클래스는 위 그림처럼 자식 클래스의 메소드를 마음대로 불러다 쓸 수 없다. 참으로 슬픈 이야기가 아닐 수 없다. ㅎㅎ

상속이라는 부분을 좀 더 파고 들어가보자. 사람이 살아가면서 무엇인가를 상속 받을 때, 꼭 한 사람에게만 상속을 받으라는 법은 없다. 클래스의 상속도 마찬가지로 여러 클래스의 속성을 상속 받을 수 있다. 이것을 다중 상속이라고 부른다. (영어로는 Multiple Inheritance라고 한다.) 위 그림은 다중 상속의 예로, clsChild 클래스는 clsParent01과 clsParent02 클래스를 모두 상속 받고 있다. 그래서, child 객체를 통해 두 개의 부모 클래스 내부에 정의된 메소드를 모두 호출할 수 있다.

다중 상속 자체는 그림에서 보는 것과 같이, 클래스 이름 뒤에 따라오는 괄호 내부에 상속 받을 클래스를 콤마 기호와 함께 나열해주는 정도로 간단하게 처리할 수 있다. 하지만, 다중 상속은 많은 고민을 필요로 한다.

객체지향 프로그래밍 언어 중에서 다중 상속을 허용하지 않는 언어들도 있다. 대표적으로 C#과 자바가 그렇다. 이들 언어가 다중 상속을 허용하지 않는 이유는 간단하다. 위 그림과 같이 부모 클래스 내부에 같은 이름의 메소드가 공통적으로 들어 있는 경우, 자식 클래스에서 어떤 부모 클래스의 메소드를 상속 받아 쓰는지가 명확하지 않기 때문이다. 이 부분은 다중 상속을 허용하는 파이썬에도 동일하게 발생하는 문제이다. mro라는 메소드를 통해 상속의 우선 순위를 확인할 수 있다고는 하지만, 그렇다고 해서 같은 이름의 멤버 변수 또는 메소드가 가져오는 문제를 완전히 해결할 수 있는 것이 아니므로, 다중 상속의 사용을 놓고 여러 의견이 분분하다.
개인적의 의견을 한 스푼 정도 더해보자면, '문제가 있으니 쓰면 안된다.' 또는 '허용했으니 써도 된다.'라는 식의 한쪽으로 치우쳐진 주장보다는 다중 상속이 가지고 있는 분명한 장점과 단점을 잘 이해하고, 필요에 따라 선택적으로 결정하는 것이 현명한 방법이 아니겠는가 라고 생각한다. 그래도 굳이 한쪽만 결정하라면, 써도 된다에 가깝다는 의미?? ㅎㅎ

 

반응형

'Programming > Python' 카테고리의 다른 글

Python: 파일로부터 데이터 읽기  (0) 2021.02.05
Python: Module  (0) 2021.01.28
Python: Class03  (0) 2021.01.26
Python: Class02  (0) 2021.01.25
Python: Class01  (0) 2021.01.24