Traits vs. Vererbung
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 55 von 91.
Nachdem du nun verstanden hast, wie Traits funktionieren, klären wir, wann du Traits und wann du Vererbung verwenden solltest. Beide ermöglichen die Wiederverwendung von Code, dienen jedoch unterschiedlichen Zwecken und haben verschiedene Eigenschaften.
Vererbung stellt eine „ist-ein“-Beziehung her. Eine Dog-Klasse, die Animal erweitert, bedeutet, dass ein Hund ein Tier ist. Die Kindklasse erbt die Identität des Elternteils und kann überall dort verwendet werden, wo der übergeordnete Typ erwartet wird.
Traits stellen eine „has-a“-Fähigkeit bereit. Wenn eine Klasse ein Loggable-Trait verwendet, verfügt sie über Protokollierungsfunktionen – aber sie wird dadurch nicht zu einem Logger. Traits fügen Verhalten hinzu, ohne zu verändern, was die Klasse grundlegend ist.
<?php
// Vererbung: Dog IST ein Animal
class Animal {
public function breathe(): void {
echo "Breathing";
}
}
class Dog extends Animal {
public function bark(): void {
echo "Woof!";
}
}
// Trait: Dog HAT Logging-Fähigkeit
trait Loggable {
public function log(string $msg): void {
echo "Log: $msg";
}
}
class Cat extends Animal {
use Loggable;
}
Wichtige Unterschiede, die du dir merken solltest:
| Aspekt | Vererbung | Traits |
|---|---|---|
| Beziehung | ist-ein | verfügt über eine Fähigkeit |
| Limitierung | Nur ein übergeordnetes Element | Mehrere Traits erlaubt |
| Typprüfung | Funktioniert mit instanceof | Keine Typidentität |
| Am besten geeignet für | Hierarchische Beziehungen | Gemeinsame Verhaltensweisen über nicht verwandte Klassen hinweg |
Verwende Vererbung, wenn Klassen eine gemeinsame Identität haben. Verwende Traits, wenn voneinander unabhängige Klassen dieselbe Funktionalität benötigen, ohne Teil desselben Stammbaums zu sein.
Aufgabe
EinfachErstellen wir ein Fahrzeugsystem, das veranschaulicht, wann Vererbung und wann Traits verwendet werden sollten. Du erstellst eine Hierarchie von Fahrzeugen, die durch Vererbung eine gemeinsame Identität teilen, während Traits übergreifende Fähigkeiten hinzufügen.
Du organisierst deinen Code über vier Dateien:
Trackable.php: Erstelle ein Trait namensTrackable, das GPS-Ortung bereitstellt. Das Trait sollte Folgendes enthalten:- Eine private Eigenschaft
$location(String) - Eine Methode
setLocation(string $location), die den aktuellen Standort speichert - Eine Methode
getLocation(), die"Location: [location]"zurückgibt
- Eine private Eigenschaft
Vehicle.php: Erstelle eine BasisklasseVehicle, die die „is-a“-Beziehung festlegt. Binde die Trait-Datei ein. Verwende Constructor Promotion, um eine geschützte Eigenschaft$brandzu definieren. Füge eine Methodedescribe()hinzu, die"Vehicle: [brand]"zurückgibt. Diese Klasse sollte das TraitTrackableverwenden, da alle Fahrzeuge in unserer Flotte über GPS verfügen werden.Car.php: Erstelle eine KlasseCar, die vonVehicleerbt. Binde die Vehicle-Datei ein. Verwende Constructor Promotion, um die Marke und eine private Eigenschaft$doors(Ganzzahl) zu übernehmen. Rufe den Konstruktor der Elternklasse mit der Marke auf. Überschreibe die Methodedescribe(), sodass sie"Car: [brand] with [doors] doors"zurückgibt.main.php: Binde die Car-Datei ein. Du erhältst drei Eingaben: einen Markennamen, eine Anzahl von Türen und eine Standortzeichenkette. Erstelle eine Instanz vonCar, setze ihren Standort und gib anschließend zwei Zeilen aus:- Das Ergebnis des Aufrufs von
describe() - Das Ergebnis des Aufrufs von
getLocation()
- Das Ergebnis des Aufrufs von
Beachte, wie Vererbung und Traits hier zusammenwirken: Car ist ein Vehicle (Vererbung legt die Identität fest), während Vehicle Ortungsfunktionalität hat (das Trait fügt Verhalten hinzu). Du könntest instanceof Vehicle verwenden, um zu prüfen, ob etwas ein Fahrzeug ist, aber es gibt keinen Typ „Trackable“, gegen den du prüfen könntest: Das ist der entscheidende Unterschied zwischen diesen beiden Ansätzen.
Probier es selbst
<?php
// Hauptdatei - Car-Instanz erstellen und testen
// TODO: Die Datei Car.php einbinden
// Eingaben lesen
$brand = trim(fgets(STDIN));
$doors = intval(trim(fgets(STDIN)));
$location = trim(fgets(STDIN));
// TODO: Eine Car-Instanz mit brand und doors erstellen
// TODO: Den Standort des Autos setzen
// TODO: Das Ergebnis von describe() ausgeben
// TODO: Das Ergebnis von getLocation() ausgeben
?>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ätzen2Namespaces & 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