Erklärung zur Lektion
Nach dieser Lektion kannst du:
Vererbung sagt, dass eine Klasse eine Art von einer anderen Klasse ist (class PremiumAccount(Account)). Komposition sagt, dass ein Objekt ein anderes Objekt hat, das ihm bei seiner Arbeit hilft (Notifier hat einen Formatter). Beide Muster sind nützlich, aber Vererbung sollte eine echte Typbeziehung abbilden und keine Abkürzung zur Wiederverwendung von Code sein.
Bei der Komposition erhält der Konstruktor des äußeren Objekts ein Hilfsobjekt und speichert es. Danach delegiert es die Arbeit: self.formatter.render(message). Wenn das Hilfsobjekt von außen bereitgestellt wird (Konstruktor-Injektion), lässt sich das Verhalten leichter wechseln und die äußere Klasse testen, ohne sie zu bearbeiten.
Erstelle im Konstruktor nicht automatisch ein Ersatz-Hilfsobjekt, wenn der Aufrufer eines übergeben hat; das würde das gewählte Verhalten ignorieren. Komposition vermeidet außerdem große Vererbungsketten, wenn das einzige Ziel darin besteht, getrennte Verantwortlichkeiten zu kombinieren.
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"))Ausgabe:
READYZwei Formatter haben dieselbe Methode, liefern aber unterschiedliche Ergebnisse.
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"))Ausgabe:
ok
[ok]Vererbung ist angemessen, wenn die Kindklasse tatsächlich ein spezialisierter Typ ihrer Elternklasse ist.
class Storage:
def kind(self):
return "storage"
class CloudStorage(Storage):
def kind(self):
return "cloud storage"
print(CloudStorage().kind())Ausgabe:
cloud storageEin Cloud-Speicher ist eine Art von Speicher; ein Service hat einen Formatter.
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))Ausgabe:
True| Beziehung | Beispiel | Bedeutung |
|---|---|---|
| Vererbung (ist-ein) | class Admin(User) | Spezialisierter Typ |
| Komposition (hat-ein) | Report(formatter) | Verwendet ein anderes Objekt |
| Dependency Injection | self.formatter = formatter | Das übergebene Hilfsobjekt behalten |
| Delegation | self.formatter.render(text) | Das Hilfsobjekt seine Aufgabe erledigen lassen |
self.formatter) zu delegieren.