Python tech/고급 파이썬 공부

Python class 상속을 통해 코드 복제를 방지하자

콜레오네 2023. 8. 15. 17:24

해당 포스팅은 [클린코드, 이제는 파이썬이다] 저서의 일부입니다.


Class 상속을 사용하면 불필요한 코드 복제를 방지할 수 있다.
하지만 상속을 남용하면 코드가 너무 얽혀서 유지보수성을 해치게 된다.
적절한 상속 사용 방법에 대해 알아보자.

상속의 작동 방식

상속은 부모 - 자식 관계이며
is a 관계라고 표현한다
부모 -> 자식 순서이며 부모 > 자식 관계이다.
따라서 부모가 가진 메서드를 자식 클래스에서 활용할 수 있고 수정할 수 있다.
하지만 그 반대는 그렇지 않다.

메소드 오버라이드 Method Override

메서드 오버라이드는 부모 클래스의 특정 메서드를 자식 클래스에서 재정의 할 수 있는 기능이다.
단, 두 메서드 이름은 같아야 한다.

class Parent:
    def saySomething():
        print("hello")


class Child(Parent):
    def saySomething():
        print("hello world")

이와 같이 부모 클래스를 상속받아 saySomething 메서드를 재정의 했다.
출력 결과는 아래와 같다.

>>> Parent.saySomething()
hello
>>> Child.saySomething()
hello world

메서드 오버라이드를 활용한다면

  • 부모 클래스를 보고 자식 클래스에서 활용될 함수를 미리 파악할 수 있다.
  • 여러가지 파생 클래스가 존재한다면, 클래스만 바꾸어서 작동 방식을 달리할 수 있다.
  • 이를 사용하지 않으면, 기능별로 너무 많은 내부 메서드가 생성되고, 이를 활용할 때도 너무 많은 if elif 문이 사용될 것이다.

super()의 사용

만약 메서드 오버라이드를 사용했지만, 완전 다른 기능을 하진 않을 수 있다.
또는 때때로 부모 클래스의 기능을 가져와야할 경우도 생긴다.
이때 super() 메서드를 사용해보자.

class Parent:
    def saySomething(self):
        print("hello")


class Child(Parent):
    def saySomething(self):
        super().saySomething()
        print("I am James")

여기서 Parent 메서드를 사용하기 위해 super() 메서드를 활용하였다.
결과를 살펴보면 이해가 쉬울 것이다.

>>> Child().saySomething()
hello
I am James

상속보단 합성이 나을 수 있다

클래스 합성(composition)은 강하게 얽히게되는 상속을 피할 수 있는 방법 중 하나다.
상속이 복잡하게 얽혀있거나 혹은 부모 클래스 수정에 따라 자식 클래스를 계속 수정해야하는 상황을 피할 수 있다.
일부 메서드만 상속받거나 혹은 attr 속성만 상속받을 수 있다.
이는 is a 관계가 아닌 has a 관계로 표현된다.

class Parent:
    def saySomething(self):
        print("hello")

class Child:
    def __init__(self):
        self.Parent = Parent()
    def saySomething(self):
        self.Parent.saySomething()
        print("I am James")

이렇게 상속을 받는 대신, 클래스를 내부 속성으로 정의하고 일부 메서드만 가져올 수 있다.
복잡한 상속 관계를 피하면서, 필요한 메서드를 활용할 수 있다.
결과는 아래와 같다.

>>> Child().saySomething()
hello
I am James

isinstance()로 클래스 간 관계를 파악하자

쉽다. 특정 클래스가 어떤 클래스의 자식 관계인지를 파악할 수 있다.

>>> class Parent:
...     def saySomething():
...         print("hello")
...
>>>
>>> class Child(Parent):
...     def saySomething():
...         print("hello world")
...
>>>
>>> child = Child()
>>> parent = Parent()
>>> isinstance(child, Child)
True
>>> isinstance(child, Parent)
True
>>> isinstance(parent, Child)
False
반응형