Объяснение к уроку
После этого урока ты сможешь:
Наследование выражает отношение, в котором один класс является разновидностью другого (class PremiumAccount(Account)). Композиция означает, что объект содержит другой объект, помогающий ему выполнять задачи (Notifier содержит Formatter). Оба паттерна полезны, но наследование должно представлять реальную связь типов, а не просто удобный способ повторного использования кода.
При композиции конструктор внешнего объекта принимает помощника и сохраняет его. Затем он делегирует выполнение задачи: self.formatter.render(message). Передача помощника извне (внедрение зависимостей через конструктор) позволяет легко менять поведение и тестировать внешний класс без его изменения.
Не создавай заменяющий объект в конструкторе заново, если вызывающий код уже передал его; это проигнорирует выбранное поведение. Композиция также помогает избегать раздутых цепочек наследования, когда целью является просто разделение ответственности.
class Formatter:
def render(self, value):
return value.upper()
class Service:
def __init__(self, formatter):
self.formatter = formatter
def output(self, value):
return self.formatter.render(value)
service = Service(Formatter())
print(service.output("ready"))Вывод:
READYДва форматтера предоставляют один и тот же метод, но возвращают разный результат.
class PlainFormatter:
def render(self, message):
return message
class BracketFormatter:
def render(self, message):
return f"[{message}]"
class Reporter:
def __init__(self, formatter):
self.formatter = formatter
def report(self, message):
return self.formatter.render(message)
print(Reporter(PlainFormatter()).report("ok"))
print(Reporter(BracketFormatter()).report("ok"))Вывод:
ok
[ok]Наследование уместно, когда дочерний класс действительно является специализированным типом родителя.
class Storage:
def kind(self):
return "storage"
class CloudStorage(Storage):
def kind(self):
return "cloud storage"
print(CloudStorage().kind())Вывод:
cloud storageОблачное хранилище является разновидностью хранилища; сервис содержит форматтер.
class RetryPolicy:
def can_retry(self, attempt):
return attempt < 3
class Worker:
def __init__(self, policy):
self.policy = policy
def should_retry(self, attempt):
return self.policy.can_retry(attempt)
print(Worker(RetryPolicy()).should_retry(2))Вывод:
True| Отношение | Пример | Значение |
|---|---|---|
| Наследование (is-a) | class Admin(User) | Специализированный тип |
| Композиция (has-a) | Report(formatter) | Использует другой объект |
| Внедрение зависимостей | self.formatter = formatter | Сохраняет переданного помощника |
| Делегирование | self.formatter.render(text) | Просит помощника выполнить задачу |
self.formatter).