В чем основной недостаток использования абстрактных классов для реализации интерфейсов в Python

«В чем основной недостаток использования абстрактных классов для реализации интерфейсов в Python» — вопрос из категории ООП, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Основной недостаток в том, что проверка на полную реализацию интерфейса происходит во время выполнения (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) выявлять несоответствия интерфейсу еще до запуска кода.