Komposition vs. Vererbung
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 56 von 91.
Im vorherigen Kapitel hast du gelernt, dass Traits eine „hat-eine“-Fähigkeit bereitstellen, während Vererbung eine „ist-eine“-Beziehung herstellt. Komposition führt das „hat-eine“-Konzept weiter, indem sie komplexe Objekte aus einfacheren Objekten erstellt und sie als Eigenschaften speichert, anstatt von ihnen zu erben.
Bei Vererbung könnte ein Car Vehicle erweitern. Bei Komposition enthält ein Car-Objekt ein Engine-Objekt:
<?php
class Engine {
public function start(): string {
return "Engine started";
}
}
class Car {
private Engine $engine;
public function __construct() {
$this->engine = new Engine();
}
public function start(): string {
return $this->engine->start();
}
}
$car = new Car();
echo $car->start();
Ausgabe:
Engine startedDie Klasse Car erbt nicht von Engine – sie besitzt eine Instanz davon. Dieser Ansatz bietet erhebliche Vorteile: Du kannst den Motor durch eine andere Implementierung ersetzen, die Klassen bleiben lose gekoppelt, und du vermeidest die starren Hierarchien, die tiefe Vererbung erzeugt.
Eine gängige Richtlinie in der OOP lautet „Komposition gegenüber Vererbung bevorzugen.“ Vererbung funktioniert gut bei echten Typhierarchien (ein Dog ist tatsächlich ein Animal), aber Komposition spielt ihre Stärken aus, wenn du Funktionalität aus unabhängigen Teilen zusammensetzt. Du kannst mehrere Objekte kombinieren, sie zur Laufzeit ersetzen und Komponenten isoliert testen.
Die nächste Lektion behandelt die Abhängigkeitsinjektion, die direkt auf der Komposition aufbaut, indem sie steuert, wie Objekte ihre Abhängigkeiten erhalten.
Aufgabe
EinfachErstellen wir ein Computersystem mithilfe von Komposition, bei dem ein Computer aus separaten Komponentenobjekten zusammengesetzt wird, anstatt von ihnen zu erben. Dies zeigt, wie Komposition es dir ermöglicht, komplexe Objekte aus einfacheren, unabhängigen Teilen zu erstellen.
Du organisierst deinen Code über drei Dateien:
Processor.php: Erstelle eineProcessor-Klasse, die eine CPU repräsentiert. Verwende Konstruktor-Promotion, um ein privates$model(String) und ein privates$cores(Ganzzahl) zu definieren. Füge eine MethodegetSpecs()hinzu, die"[model] ([cores] cores)"zurückgibt.Memory.php: Erstelle eineMemory-Klasse, die RAM repräsentiert. Verwende Konstruktor-Promotion, um ein privates$size(Ganzzahl, die GB repräsentiert) zu definieren. Füge eine MethodegetCapacity()hinzu, die"[size]GB RAM"zurückgibt.main.php: Binde beide Komponentendateien ein und erstelle eineComputer-Klasse, die Komposition verwendet. DerComputersollte:- ein
Processor-Objekt und einMemory-Objekt als private Eigenschaften speichern - in seinem Konstruktor ein Prozessormodell, eine Anzahl von Kernen und eine Speichergröße akzeptieren
- die Komponentenobjekte während der Konstruktion intern erstellen
- eine
describe()-Methode besitzen, die"Computer with [processor specs] and [memory capacity]"zurückgibt
Du erhältst drei Eingaben: ein Prozessormodell, eine Anzahl von Kernen und eine Speichergröße in GB. Erstelle mit diesen Angaben einen
Computerund gib das Ergebnis des Aufrufs vondescribe()aus.- ein
Beachte, dass der Computer weder Processor noch Memory erweitert. Er enthält sie. Diese „Hat-eine“-Beziehung durch Komposition hält jede Komponente unabhängig und wiederverwendbar und ermöglicht es dem Computer zugleich, bei Bedarf Aufgaben an seine Bestandteile zu delegieren.
Probier es selbst
<?php
require_once 'Processor.php';
require_once 'Memory.php';
class Computer
{
// TODO: Definiere private Eigenschaften zum Speichern von Processor- und Memory-Objekten
// TODO: Konstruktor sollte Prozessormodell, Kernanzahl und Speichergröße akzeptieren
// und die Komponentenobjekte intern erstellen
public function __construct()
{
// TODO: Erstelle Processor- und Memory-Objekte und speichere sie
}
// TODO: Implementiere die describe()-Methode, die zurückgibt
// "Computer with [processor specs] and [memory capacity]"
public function describe(): string
{
// TODO: Delegiere an die Komponentenobjekte und gib einen formatierten String zurück
}
}
// Eingabe lesen
$processorModel = trim(fgets(STDIN));
$cores = intval(fgets(STDIN));
$memorySize = intval(fgets(STDIN));
// TODO: Erstelle einen Computer mit den gegebenen Spezifikationen und gib das Ergebnis von describe() aus
?>Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen10Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungDependency InjectionAnonyme KlassenEnums (PHP 8.1)Fibers (PHP 8.1)Objektklonen im DetailGeneratoren & Iteratoren2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler