Ответ
Основной недостаток в том, что проверка на полную реализацию интерфейса происходит во время выполнения (runtime) при попытке создать экземпляр класса, а не на этапе статического анализа или определения класса.
Это означает, что ошибка из-за нереализованного абстрактного метода может проявиться только после запуска приложения, а не во время разработки или компиляции.
Пример:
from abc import ABC, abstractmethod
class StorageInterface(ABC):
@abstractmethod
def save(self, data: bytes):
pass
@abstractmethod
def load(self, key: str) -> bytes:
pass
# Класс определен без ошибок, хотя метод load() не реализован
class FileStorage(StorageInterface):
def save(self, data: bytes):
print("Data saved to file.")
# Ошибка возникнет только здесь, при попытке создания объекта
# TypeError: Can't instantiate abstract class FileStorage
# with abstract method load
try:
storage = FileStorage()
except TypeError as e:
print(e)
Ключевые недостатки:
- Позднее обнаружение ошибок: Ошибки выявляются только при инстанцировании, а не при определении класса.
- Отсутствие проверки сигнатур:
abcне проверяет соответствие типов и количества аргументов в реализованных методах. - Жесткая связь: Класс-реализация должен явно наследоваться от абстрактного класса, что создает сильную связь в иерархии классов.
Современная альтернатива:
Для определения интерфейсов в современном Python предпочтительнее использовать Протоколы (typing.Protocol), введенные в PEP 544. Они поддерживают статическую типизацию (утиная типизация) и позволяют статическим анализаторам (как Mypy) выявлять несоответствия интерфейсу еще до запуска кода.