본문 바로가기

추상 클래스와 인터페이스

추상 클래스(ABC)는 '@abstractmethod'로 선언된 메서드를 자식 클래스에서 반드시 구현하도록 강제합니다. Python에는 인터페이스 키워드가 없지만 추상 클래스로 유사하게 구현할 수 있습니다.

1. 추상 클래스

"만약 메타클래스가 필요한지 궁금하다면, 이건 필요하지 않다는 의미입니다." - The Zen of Python의 저자 팀 피터스

메타클래스는 견고한 파이썬에서도 다루지 않습니다. 팀 피터스는 99%의 경우 메타클래스가 필요없다고 얘기하였습니다. 추상클래스 또한 마찬가지입니다. 대부분의 파이썬 사용자에게 해당 내용은 필요하지 않습니다. 필요한 경우에 찾아보시길 바랍니다.

파이썬에서 추상 클래스(Abstract Base Class, ABC)는 본문 없이 이름만 선언해둔 메서드(추상 메서드)를 가진 클래스입니다. 자기 자신은 그 메서드를 구현하지 않는 대신, 이를 상속받는 자식 클래스에게 반드시 구현하라고 강제합니다. abc 모듈의 ABC 클래스와 abstractmethod 데코레이터를 사용하여 추상 클래스와 추상 메서드를 정의합니다.

아래와 같이 추상 클래스에 do_something을 정의해놓고 만약 이 클래스를 상속하는 클래스에서 해당 메서드를 재정의하지 않으면 에러가 납니다.

from abc import ABC, abstractmethod

class AbstractClassExample(ABC):

    @abstractmethod
    def do_something(self):
        pass

class Person(AbstractClassExample):

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

    def print_name(self):
        print(f'제 이름은 {self.name}입니다.')

hojun = Person('hojun')
hojun.print_name()
# 출력
---------------------------
TypeError Traceback (most recent call last)
<ipython-input-34-15cbe4aeb172> in <cell line: 17>()
     16
---> 17 hojun = Person('hojun')
     18 hojun.print_name()

TypeError: Can't instantiate abstract 
class Person with abstract method do_something

아래와 같이 추상 클래스에 선언된 메서드를 자식 클래스에서 오버라이딩(재정의)하여 사용해야 합니다.

from abc import ABC, abstractmethod

class AbstractClassExample(ABC):

    @abstractmethod
    def do_something(self):
        pass

class Person(AbstractClassExample):

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

    def print_name(self):
        print(f'제 이름은 {self.name}입니다.')

    def do_something(self):
        pass

hojun = Person('Jun')
hojun.print_name()
# 출력
제 이름은 Jun입니다.

2. 인터페이스

인터페이스는 객체가 어떤 메서드를 구현해야 하는지 정의한 것입니다. Python에서는 다른 언어들과 달리 인터페이스라는 내장 키워드나 구조가 없습니다. 그러나 추상 클래스를 이용하여 인터페이스처럼 동작하는 클래스를 만들 수 있습니다. 이렇게 추상 클래스로 이를 상속받은 클래스가 특정 메서드를 구현하게 강제함으로써 구조적인 특징을 가질 수 있도록 합니다.

from abc import ABC, abstractmethod

class MyInterface(ABC):

    @abstractmethod
    def method1(self):
        pass

    @abstractmethod
    def method2(self):
        pass

Python 기본 라이브러리를 확인하면 이러한 추상 클래스들이 어떻게 사용되는지 확인할 수 있습니다. 아래 폴더에서 기본적으로 내장되어 있는 라이브러리들을 확인할 수 있습니다. 이 설치 경로는 OS에 따라 다릅니다. Lib > importlib > abc.py와 같은 파일을 확인해보면 추상 클래스가 어떻게 사용되는지 확인할 수 있습니다.

우리가 이미 쓰고 있는 자료형들도 사실 추상 클래스로 묶여 있습니다. collections.abc 모듈이 그 목록을 담고 있는데, 이를 이용하면 "리스트인가"가 아니라 "순회할 수 있는가", "길이를 잴 수 있는가"처럼 능력을 기준으로 확인할 수 있습니다.

from collections.abc import Iterable, Sized

print(isinstance([1, 2, 3], Iterable))  # True
print(isinstance('hello', Iterable))    # True
print(isinstance(10, Iterable))         # False
print(isinstance({1, 2}, Sized))        # True

직접 만든 클래스에 이러한 추상 클래스를 상속시키면, 필요한 매직 메서드를 빠뜨렸을 때 인스턴스 생성 단계에서 바로 잡아줍니다.

from collections.abc import Sized

class Basket(Sized):
    def __init__(self, items):
        self.items = items

    def __len__(self):  # 이 메서드를 지우면 인스턴스를 만들 수 없습니다.
        return len(self.items)

b = Basket([1, 2, 3])
print(len(b))
추상 클래스와 인터페이스 - 견고한 파이썬 | 위니버시티