Абстрактные классы - это классы, которые предназначены для наследования, но избегают реализации конкретных методов, оставляя только сигнатуры методов, которые должны реализовывать подклассы.
from abc import ABCMeta
class AbstractClass(object):
# атрибут метакласса всегда должен
# быть установлен как переменная класса
__metaclass__ = ABCMeta
# декоратор abstractmethod регистрирует этот метод как undefined
@abstractmethod
def virtual_method_subclasses_must_define(self):
# Можно оставить полностью пустым
# или предоставить базовую реализацию
# Обратите внимание, что обычно пустая интерпретация
# неявно возвращает `None`, но при регистрации
# это поведение больше не применяется.
123456789101112131415
Причины использования абстрактных классов
class MontyPython:
def joke(self):
raise NotImplementedError()
def punchline(self):
raise NotImplementedError()
class ArgumentClinic(MontyPython):
def joke(self):
return "Hahahahahah"
12345678910
Когда мы создаем объект и называем это два метода, мы получим ошибку (как и ожидалось) с punchline() метод.
sketch = ArgumentClinic()
sketch.punchline()
# AttributeError: 'ArgumentClinic' object has no attribute 'punchline'
1234
Этого можно избежать, используя модуль Abstract Base Class (ABC).
from abc import ABCMeta, abstractmethod
class MontyPython(metaclass=ABCMeta):
@abstractmethod
def joke(self):
pass
@abstractmethod
def punchline(self):
pass
# у наследуемого класса 2 @abstractmethod, а мы использовали только один
class ArgumentClinic(MontyPython):
def joke(self):
return "Hahahahahah"
c = ArgumentClinic()
# TypeError: "Can't instantiate abstract class ArgumentClinic with abstract methods punchline"
12345678910111213141516
На этот раз, когда мы пытаемся создать экземпляр объекта из неполного класса, мы немедленно получаем TypeError!
class ArgumentClinic(MontyPython):
def joke(self):
return "Hahahahahah"
def punchline(self):
return "Send in the constable!"
c = ArgumentClinic()
c
# <__main__.ArgumentClinic object at 0x7fee680d3640>
1234567891011
Простой пример с множественным наследованием
class A(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def do(self):
pass
class B(object):
def do(self):
print "do"
class C(B, A):
pass
c = C()
123456789101112131415