
Абстрактный класс – класс, содержащий один и более абстрактных методов.
Абстрактный метод – метод, который объявлен, но не реализован.
Абстрактный класс не может быть инстанциирован (создан его экземпляр). Нужно наследовать этот класс и реализовать (переопределить) все абстрактные методы, и только после этого можно создавать экземпляры такого наследника.
В Python нет синтаксической поддержки абстрактных классов, но есть встроенный модуль abc (расшифровка – abstract base classes), который помогает проектировать абстрактные сущности.
Абстрактный класс наследуют от ABC
(Python 3.4+) или указывают метакласс ABCMeta
(для Python 3.0+):
from abc import ABC, ABCMeta class Hero(ABC): ... # или: class Hero(metaclass=ABCMeta): ...
Любой из вариантов работает, первый современнее и короче. На данном этапе мы можем создавать объекты этих классов, потому что в них пока не абстрактных методов. Добавим:
from abc import ABC, abstractmethod class Hero(ABC): @abstractmethod def attack(self): pass
Hero()
– выдаст ошибку "TypeError: Can't instantiate abstract class Hero with abstract methods attack",
которая говорит, что в классе Hero
есть абстрактный метод attack
. Мы вставили в него заглушку pass
, но вообще там может быть какая-то реализация. Отнаследуем от героя Hero
– конкретный подкласс лучника Archer
:
class Archer(Hero): def attack(self): print('выстрел из лука') Archer().attack()
Вот объект Archer
мы можем уже создать и использовать реализацию метода attack
.
Кроме обычных методов, абстрактными можно обозначить и статические, классовые методы, а также свойства:
class C(ABC): @classmethod @abstractmethod def my_abstract_classmethod(cls): ... @staticmethod @abstractmethod def my_abstract_staticmethod(): ... @property @abstractmethod def my_abstract_property(self): ... @my_abstract_property.setter @abstractmethod def my_abstract_property(self, val): ...
Абстрактные классы широко фигурируют в ООП, часто всплывают в шаблонах проектирования. Они говорят, что общий интерфейс уже обозначен, но этот класс еще не предназначен для использования, кроме как для наследования от него конкретных потомков.
Формально говоря, абстрактные классы для Python не являются чем-то необходимым в силу динамичности языка. Если мы выкинем все упоминания абстрактности классов и методов из рабочего кода, он продолжит работать, как и ранее. Абстрактные классы нужны на этапе проектирования или расширения кода, чтобы обеспечивать «правильные» взаимодействия новых классов, защищая от создания экземпляров абстрактных классов. Важно помнить, что эта защита срабатывает на этапе выполнения программы, а не компиляции, как в языках Java, C++ или C#!
Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈