Menu
Coddy logo textTech

Traits vs. Vererbung

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 55 von 91.

Nachdem Sie nun verstehen, wie Traits funktionieren, lassen Sie uns klären, wann Traits im Gegensatz zur Vererbung verwendet werden sollten. Beide ermöglichen die Wiederverwendung von Code, aber sie dienen unterschiedlichen Zwecken und haben unterschiedliche Merkmale.

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 der Elternklasse und kann überall dort verwendet werden, wo der Typ der Elternklasse erwartet wird.

Traits bieten eine „has-a“-Fähigkeit. Wenn eine Klasse ein Loggable-Trait verwendet, besitzt sie Logging-Funktionalität – aber sie wird nicht zu einem Logger. Traits fügen Verhalten hinzu, ohne das grundlegende Wesen der Klasse zu verändern.

<?php
// Vererbung: Hund IST ein Tier
class Animal {
    public function breathe(): void {
        echo "Breathing";
    }
}

class Dog extends Animal {
    public function bark(): void {
        echo "Woof!";
    }
}

// Trait: Hund HAT Protokollierungsfunktionen
trait Loggable {
    public function log(string $msg): void {
        echo "Log: $msg";
    }
}

class Cat extends Animal {
    use Loggable;
}

Wichtige Unterschiede, die man sich merken sollte:

AspektVererbungTraits
Beziehungis-ahas-a capability
EinschränkungNur ein ElternteilMehrere Traits erlaubt
TypprüfungFunktioniert mit instanceofKeine Typidentität
Bestens geeignet fürHierarchische BeziehungenGemeinsame Verhaltensweisen über nicht verwandte Klassen hinweg

Verwenden Sie Vererbung, wenn Klassen eine gemeinsame Identität teilen. Verwenden Sie Traits, wenn nicht verwandte Klassen dieselbe Funktionalität benötigen, ohne Teil desselben Stammbaums zu sein.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Fahrzeugsystem bauen, das demonstriert, wann Vererbung gegenüber Traits verwendet werden sollte. Sie werden eine Hierarchie von Fahrzeugen erstellen, die durch Vererbung eine gemeinsame Identität teilen, während Sie durch Traits querschnittliche Funktionen hinzufügen.

Sie werden Ihren Code über vier Dateien organisieren:

  • Trackable.php — Erstellen Sie einen Trait namens Trackable, der GPS-Tracking-Funktionen bereitstellt. Der Trait sollte Folgendes haben:
    • Eine private Eigenschaft $location (string)
    • Eine Methode setLocation(string $location), die den aktuellen Standort speichert
    • Eine Methode getLocation(), die "Location: " . $this->location zurückgibt
    Dieser Trait repräsentiert eine "hat-ein"-Fähigkeit — jedes Fahrzeug kann Tracking haben, aber Tracking zu haben, macht etwas nicht automatisch zu einem Fahrzeug.
  • Vehicle.php — Erstellen Sie eine Basisklasse Vehicle, die die "ist-ein"-Beziehung herstellt. Binden Sie die Trait-Datei ein. Verwenden Sie Constructor Promotion, um eine geschützte Eigenschaft $brand zu definieren. Fügen Sie eine Methode describe() hinzu, die "Vehicle: " . $this->brand zurückgibt. Diese Klasse sollte den Trackable Trait verwenden, da alle Fahrzeuge in unserer Flotte über GPS verfügen werden.
  • Car.php — Erstellen Sie eine Klasse Car, die Vehicle erweitert. Binden Sie die Vehicle-Datei ein. Verwenden Sie Constructor Promotion, um die Marke und eine private Eigenschaft $doors (integer) zu akzeptieren. Rufen Sie den Eltern-Konstruktor mit der Marke auf. Überschreiben Sie die Methode describe(), sodass sie "Car: " . $this->brand . " with " . $this->doors . " doors" zurückgibt.
  • main.php — Binden Sie die Car-Datei ein. Sie erhalten drei Eingaben: einen Markennamen, eine Anzahl von Türen und einen Standort-String. Erstellen Sie eine Car-Instanz, setzen Sie deren Standort und geben Sie dann zwei Zeilen aus:
    • Das Ergebnis des Aufrufs von describe()
    • Das Ergebnis des Aufrufs von getLocation()

Beachten Sie, wie Vererbung und Traits hier zusammenarbeiten: Car ist ein Vehicle (Vererbung stellt die Identität her), während Vehicle eine Tracking-Funktion hat (der Trait fügt Verhalten hinzu). Sie könnten instanceof Vehicle verwenden, um zu prüfen, ob etwas ein Fahrzeug ist, aber es gibt keinen "Trackable"-Typ, gegen den man prüfen könnte — das ist der entscheidende Unterschied zwischen diesen beiden Ansätzen.

Spickzettel

Verwenden Sie Vererbung für „is-a“-Beziehungen und Traits für „has-a“-Fähigkeiten.

Vererbung stellt Identität her – eine Kindklasse ist ein Typ der Elternklasse und kann überall dort verwendet werden, wo der Elterntyp erwartet wird.

Traits fügen Verhalten hinzu, ohne die Klassenidentität zu ändern – eine Klasse hat eine Funktionalität, wird aber nicht zu diesem Ding.

<?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: Cat HAT Logging-Fähigkeit
trait Loggable {
    public function log(string $msg): void {
        echo "Log: $msg";
    }
}

class Cat extends Animal {
    use Loggable;
}
AspektVererbungTraits
Beziehungis-ahas-a capability
EinschränkungNur ein ElternteilMehrere Traits erlaubt
TypprüfungFunktioniert mit instanceofKeine Typidentität
Bestens geeignet fürHierarchische BeziehungenGemeinsame Verhaltensweisen über nicht verwandte Klassen hinweg

Verwenden Sie Vererbung für hierarchische Beziehungen, bei denen Klassen eine gemeinsame Identität teilen. Verwenden Sie Traits für gemeinsame Verhaltensweisen über nicht verwandte Klassen hinweg.

Probier es selbst

<?php
// Hauptdatei - Erstellen und Testen der Car-Instanz

// 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 Marke und Türen erstellen

// TODO: Den Standort des Autos festlegen

// TODO: Das Ergebnis von describe() ausgeben

// TODO: Das Ergebnis von getLocation() ausgeben
?>
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung