이 강의는 python3 문법입니다.
추상클래스라는 용어는 C++의 추상클래스와 비슷하게 이해할 수 있다. 자바(java)라면 interface라 볼 수 있다.
C++이나 JAVA를 몰라도 상관은 없다.
쉽게 말해 추상클래스는 메소드의 구체적인 구현이 없는 클래스를 말한다. 이런 클래스를 왜 만들까 한번 10초만 고민해보자.
추상클래스의 목적은 일종의 틀을 제공해주는 역할을 한다. 이 틀은 추상클래스를 상속하는 클래스들에게 특정 메소드의 구현을 강제하는 효과가 있다. 앞서 말한 C++의 추상클래스라면 메소드를 _순수 가상함수_라는 형식으로 정의하여 이를 상속하는 클래스들에게 순수 가상함수를 강제구현하도록 하는 지시를 하는 것이다. 자바의 경우는 interface가 같은 역할을 한다.
우선 본론에 들어가기 전에 파이썬에서 일반적인 상속을 알아보자.
# 부모 클래스
class Animal():
def act(self):
... # 구현해 주세요.
# 자식 클래스
class Cat(Animal):
def myAct(self):
print("Do my Act!")
if __name__ == "__main__":
Cat().myAct()
위 코드를 실행해보면 Do my Act!
가 콘솔에 찍힌다. 얼핏 봐서는 이 코드가 문제가 있는 코드인지 모를 수 있다. 위 예는 간단하여 act
가 하위클래스에 구현되지 않았다는 걸 알 수 있지만, 코드가 복잡해진다면 쉽게 발견하기 힘들 수 있다.
다시 말해, 이 코드의 문제점은 부모클래스(Animal
)에서 선언한 act
메소드가 어디에서도 구현되지 않았다는 것이다. 그럼에도 이 코드는 잘 동작하며 자식클래스(Cat
)는 부모클래스의 코드를 들춰보지 않는 한 act
를 구현해야할 지도 모르기 때문에 Animal
추상클래스를 제공한 자의 의도에 맞지 않는 구현이 된 것이다.
추상클래스의 중요성
우선 추상클래스를 인터페이스와 같다고 생각하자. 인터페이스란 일종의 포맷 스펙이다. 사용자는 특정 물건을 사용할 때 인터페이스가 맞는지 확인해야 한다. 인터페이스는 형식을 강제한다. 우리가 전기를 쓸 때 꼽는 돼지코의 모양이 동일한 규격인 것 처럼.
다시 위 예로 돌아가자.
누군가 Animal
클래스를 만들 때 act
메소드가 반드시 구현되길 원한다고 가정하자. 앞서 예제와 같은 방식으로는 abc
메소드의 구현을 강제할 수 없다.
이를 강제하기 위해 파이썬은 abc모듈을 제공한다. abc
는 abstract class의 약자다.
from abc import ABCMeta, abstractmethod
class Animal(metaclass= ABCMeta):
@abstractmethod
def act(self):
...
class Cat(Animal):
def myAct(self):
print("Do my Act!")
if __name__ == "__main__":
Cat().myAct()
- 앞서 예제의
Animal
클래스에ABCMeta
설정을 하였다. - 상속받는 클래스에서 구현을 강제할 메소드에 @abstratmethod 장식자를 추가하였다.
- 이제 다시 코드를 실행해보면 에러가 발생한다.
Traceback (most recent call last): File "abc.ex.py", line 13, in <module> Cat().myAct() TypeError: Can't instantiate abstract class Cat with abstract methods act
abc
추상 메소드를 가진 Cat
추상 클래스를 초기화 할 수 없다고?
이 에러는 C++에서도 비슷한 상황에서 비슷한 에러가 난다. 그냥 abc
추상메소드를 구현하면 해결된다고 생각하자.
주의할 점은 이 에러는 클래스 정의단계에서는 발생하지 않는다. Cat()
라는 객체 생성단계에서 발생하므로 주의해야한다.
추상 메소드의 구현
from abc import ABCMeta, abstractmethod
class Animal(metaclass= ABCMeta):
@abstractmethod
def act(self):
...
class Cat(Animal):
def act(self): # 추상메소드 구현
print("Do my Act!")
if __name__ == "__main__":
Cat().act()
추상메소드를 구현하였다. 에러는 발생하지 않고 Do my Act!
가 깔끔하게 출력된다.
참고
metaclass=ABCMeta
가 아닌 ABC
를 상속하여 구현해도 된다.
from abc import ABC, abstractmethod
class Animal(ABC):
...
모든 설명은 추상베이스클래스에 기반합니다.