← Назад к вопросам

Как реализовать интерфейс?

1.0 Junior🔥 241 комментариев
#Python Core#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как реализовать интерфейс

В Python интерфейсы реализуются через абстрактные классы из модуля abc (Abstract Base Classes). Это позволяет определить контракт, который обязан выполнять любой класс, наследующий интерфейс.

Базовая реализация интерфейса

from abc import ABC, abstractmethod

# Определение интерфейса (абстрактного класса)
class PaymentProcessor(ABC):
    """Интерфейс для обработки платежей"""
    
    @abstractmethod
    def process_payment(self, amount: float) -> bool:
        """Обработать платёж"""
        pass
    
    @abstractmethod
    def refund(self, transaction_id: str) -> bool:
        """Вернуть деньги"""
        pass

# Реализация интерфейса
class CreditCardProcessor(PaymentProcessor):
    """Конкретная реализация для кредитных карт"""
    
    def process_payment(self, amount: float) -> bool:
        print(f"Обработка платежа {amount} через кредитную карту")
        # Логика обработки платежа
        return True
    
    def refund(self, transaction_id: str) -> bool:
        print(f"Возврат платежа {transaction_id}")
        return True

# Использование
processor = CreditCardProcessor()
processor.process_payment(100.0)  # Обработка платежа 100.0 через кредитную карту

# Попытка создать экземпляр интерфейса — ошибка
# payment = PaymentProcessor()  # TypeError: Can't instantiate abstract class

Ошибка при неполной реализации

class IncompleteProcessor(PaymentProcessor):
    """Неполная реализация интерфейса"""
    
    def process_payment(self, amount: float) -> bool:
        return True
    
    # refund не реализован!

# Это вызовет ошибку
processor = IncompleteProcessor()
# TypeError: Can't instantiate abstract class IncompleteProcessor with abstract methods refund

Абстрактные методы с телом (поведение по умолчанию)

from abc import ABC, abstractmethod

class DatabaseConnection(ABC):
    """Интерфейс для подключения к БД"""
    
    @abstractmethod
    def connect(self) -> bool:
        """Установить соединение"""
        # Может быть тело метода с логикой по умолчанию
        print("Инициализация соединения")
    
    @abstractmethod
    def execute(self, query: str) -> list:
        """Выполнить запрос"""
        pass
    
    def close(self):
        """Закрыть соединение (не абстрактный)"""
        print("Соединение закрыто")

class PostgreSQLConnection(DatabaseConnection):
    def connect(self) -> bool:
        super().connect()  # Вызовем поведение по умолчанию
        print("PostgreSQL соединение установлено")
        return True
    
    def execute(self, query: str) -> list:
        print(f"Выполняю SQL: {query}")
        return []

db = PostgreSQLConnection()
db.connect()  # Инициализация соединения\nPostgreSQL соединение установлено

Абстрактные свойства (properties)

from abc import ABC, abstractmethod

class Animal(ABC):
    """Интерфейс для животного"""
    
    @property
    @abstractmethod
    def name(self) -> str:
        """Имя животного"""
        pass
    
    @property
    @abstractmethod
    def species(self) -> str:
        """Вид животного"""
        pass
    
    @abstractmethod
    def make_sound(self) -> str:
        pass

class Dog(Animal):
    def __init__(self, dog_name: str):
        self._name = dog_name
    
    @property
    def name(self) -> str:
        return self._name
    
    @property
    def species(self) -> str:
        return "Canine"
    
    def make_sound(self) -> str:
        return "Woof!"

dog = Dog("Buddy")
print(dog.name)      # Buddy
print(dog.species)   # Canine
print(dog.make_sound())  # Woof!

Интерфейсы с типами данных

from abc import ABC, abstractmethod
from typing import Generic, TypeVar, List

T = TypeVar('T')

class Repository(ABC, Generic[T]):
    """Интерфейс для работы с репозиториями"""
    
    @abstractmethod
    def get_by_id(self, id: int) -> T | None:
        pass
    
    @abstractmethod
    def get_all(self) -> List[T]:
        pass
    
    @abstractmethod
    def save(self, entity: T) -> T:
        pass
    
    @abstractmethod
    def delete(self, id: int) -> bool:
        pass

class User:
    def __init__(self, id: int, name: str):
        self.id = id
        self.name = name

class UserRepository(Repository[User]):
    def __init__(self):
        self.users: dict[int, User] = {}
    
    def get_by_id(self, id: int) -> User | None:
        return self.users.get(id)
    
    def get_all(self) -> List[User]:
        return list(self.users.values())
    
    def save(self, entity: User) -> User:
        self.users[entity.id] = entity
        return entity
    
    def delete(self, id: int) -> bool:
        if id in self.users:
            del self.users[id]
            return True
        return False

# Использование
repo = UserRepository()
user = User(1, "Alice")
repo.save(user)
print(repo.get_by_id(1).name)  # Alice

Множественная реализация (миксины)

from abc import ABC, abstractmethod

class Serializable(ABC):
    @abstractmethod
    def to_dict(self) -> dict:
        pass

class Comparable(ABC):
    @abstractmethod
    def __eq__(self, other) -> bool:
        pass

class Product(Serializable, Comparable):
    def __init__(self, id: int, name: str):
        self.id = id
        self.name = name
    
    def to_dict(self) -> dict:
        return {"id": self.id, "name": self.name}
    
    def __eq__(self, other) -> bool:
        return isinstance(other, Product) and self.id == other.id

product = Product(1, "Laptop")
print(product.to_dict())  # {'id': 1, 'name': 'Laptop'}
print(product == Product(1, "Phone"))  # True (одинаковые ID)

Проверка реализации интерфейса (isinstance)

from abc import ABC, abstractmethod

class DataSource(ABC):
    @abstractmethod
    def fetch(self):
        pass

class APIDataSource(DataSource):
    def fetch(self):
        return {"data": "from API"}

api = APIDataSource()
print(isinstance(api, DataSource))  # True

# Проверка всех абстрактных методов
print(hasattr(api, 'fetch'))  # True

Реальный пример: система уведомлений

from abc import ABC, abstractmethod
from typing import List

class Notifier(ABC):
    """Интерфейс для отправки уведомлений"""
    
    @abstractmethod
    def send(self, recipient: str, message: str) -> bool:
        pass

class EmailNotifier(Notifier):
    def send(self, recipient: str, message: str) -> bool:
        print(f"Email отправлено на {recipient}: {message}")
        return True

class SMSNotifier(Notifier):
    def send(self, recipient: str, message: str) -> bool:
        print(f"SMS отправлено на {recipient}: {message}")
        return True

class PushNotifier(Notifier):
    def send(self, recipient: str, message: str) -> bool:
        print(f"Push отправлено пользователю {recipient}: {message}")
        return True

class NotificationManager:
    def __init__(self, notifiers: List[Notifier]):
        self.notifiers = notifiers
    
    def notify_all(self, recipient: str, message: str):
        for notifier in self.notifiers:
            notifier.send(recipient, message)

# Использование
manager = NotificationManager([
    EmailNotifier(),
    SMSNotifier(),
    PushNotifier()
])

manager.notify_all("user@example.com", "Важное сообщение")

Вывод: интерфейс в Python — это абстрактный класс с @abstractmethod, который определяет контракт для реализующих его классов. Это обеспечивает полиморфизм и делает код более гибким и тестируемым.