Menu

PHP Vererbung: extends, parent:: und Überschreiben

In PHP erbt eine Klasse mit class Dog extends Animal von einer anderen: Sie bekommt die öffentlichen und geschützten Eigenschaften und Methoden der Elternklasse, kann sie überschreiben und das Original trotzdem mit parent::method() aufrufen. Hier: Überschreiben, protected, final, instanceof und die Falle mit privaten Methoden.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

In PHP erbt eine Klasse mit extends von einer anderen: class Dog extends Animal gibt Dog jede öffentliche und geschützte Eigenschaft und Methode von Animal. Das Kind kann neue Methoden hinzufügen, geerbte überschreiben, indem es eine Methode mit demselben Namen deklariert, und das Original mit parent::method() aufrufen.

Dog hat keinen Konstruktor, also verwendet es den von Animal, und deshalb funktioniert new Dog('Rex'). Eine Kindklasse kann nur eine Elternklasse erweitern; PHP hat keine Mehrfachvererbung von Klassen.

Die Methode der Elternklasse mit parent:: aufrufen

Überschreiben ersetzt die Methode der Elternklasse vollständig. Um sie zu erweitern, statt sie zu ersetzen, rufst du im Kind parent::method() auf und baust auf dem Ergebnis auf:

Dasselbe funktioniert bei Konstruktoren mit parent::__construct(...), was die Seite zum Konstruktor behandelt, einschließlich dessen, was passiert, wenn du es vergisst.

protected vs private in Kindklassen

Ein protected-Member ist vor äußerem Code verborgen, aber für jede Klasse der Familie sichtbar. Ein private-Member ist nur in der Klasse sichtbar, die es deklariert, also sieht eine Kindklasse es überhaupt nicht:

isset($this->pin) ist im Kind falsch, weil das Kind keinen Zugriff auf das private $pin der Elternklasse hat, während die eigene Methode hasPin() der Elternklasse es weiterhin liest. Verwende protected für das, worauf Unterklassen aufbauen sollen, und private für Details, die du frei ändern können willst.

Polymorphie und instanceof

Code, der gegen den Elterntyp geschrieben ist, funktioniert mit jedem Kind. Jedes Objekt führt seine eigene Version einer überschriebenen Methode aus, also behandelt eine Schleife alle. instanceof prüft, ob ein Objekt zu einer Klasse oder einem ihrer Kinder gehört:

Wenn die Elternklasse nie allein verwendet werden soll (ein einfaches Shape mit Fläche 0 ergibt wenig Sinn), machst du sie zu einer abstrakten Klasse und deklarierst area() als abstract.

Regeln beim Überschreiben: Signaturen müssen kompatibel bleiben

Eine überschreibende Methode muss mindestens das annehmen, was die Elternklasse angenommen hat, und etwas zurückgeben, das die Aufrufer der Elternklasse verwenden können. Du darfst einen optionalen Parameter hinzufügen, einen Parametertyp erweitern oder einen Rückgabetyp einschränken; du darfst keinen Pflichtparameter hinzufügen und keine öffentliche Methode privat machen.

Ändere string $sep = ',' in ein Pflicht-string $sep, und PHP weigert sich, die Klasse zu kompilieren, mit einem fatalen Fehler („Declaration of CsvExporter::export(array rows,stringrows, string sep): string must be compatible with Exporter::export(array $rows): string“).

Finale Klassen und Methoden

final beendet die Vererbung an dieser Stelle. Eine final-Methode kann nicht überschrieben werden, und eine final class lässt sich nicht erweitern. Beides wird beim Kompilieren der Datei geprüft, also startet das Skript gar nicht erst:

<?php
class Payment
{
    final public function charge(int $cents): string
    {
        return "charged $cents";
    }
}

class FreePayment extends Payment
{
    public function charge(int $cents): string
    {
        return 'free';
    }
}
PHP Fatal error:  Cannot override final method Payment::charge() in /home/index.php on line 12

Bei einer finalen Klasse lautet die Meldung Class B cannot extend final class A. Markiere eine Methode als final, wenn die Elternklasse sich darauf verlässt, dass sie sich genau auf eine Weise verhält, zum Beispiel eine Methode, die Berechtigungen prüft, bevor sie irgendetwas anderes tut.

Die Falle mit privaten Methoden

Eine private Methode wird nicht vererbt, also überschreibt eine Methode des Kindes mit demselben Namen sie nicht. Code in der Elternklasse ruft weiterhin seine eigene private Version auf, was alle überrascht, die erwarten, dass die Methode des Kindes läuft:

greet() gibt weiterhin Hello aus: $this->word() in der Elternklasse löst sich zur privaten Methode der Elternklasse auf. Ändere in Greeter private in protected und führe den Code erneut aus; jetzt ist die Methode des Kindes ein echtes Überschreiben, und greet() sagt Bonjour.

Häufig gestellte Fragen

Wie funktioniert extends in PHP?

class Dog extends Animal macht Dog zu einem Kind von Animal. Ein Dog-Objekt hat jede öffentliche und geschützte Eigenschaft und Methode von Animal, kann eigene hinzufügen und geerbte Methoden ersetzen (überschreiben), indem es eine Methode mit demselben Namen deklariert.

Wie rufe ich in PHP die Methode der Elternklasse auf?

Mit parent::methodName() in der Methode des Kindes, zum Beispiel return parent::describe() . ' and more';. Beim Konstruktor ist es parent::__construct(...).

Unterstützt PHP Mehrfachvererbung?

Nein. Eine Klasse kann nur eine Elternklasse erweitern. Um Verhalten aus mehreren Quellen zu teilen, implementierst du mehrere Interfaces (class A implements B, C) und verwendest Traits (use Loggable, Timestamps;).

Was bedeutet final in PHP?

Eine final-Methode kann von keiner Kindklasse überschrieben werden, und eine final class lässt sich gar nicht erweitern. Ein Verstoß gegen eine der Regeln ist beim Kompilieren der Klasse ein fataler Fehler, zum Beispiel Cannot override final method A::f().

Kann eine Kindklasse in PHP auf eine private Eigenschaft der Elternklasse zugreifen?

Nein. Ein private-Member gehört nur der Klasse, die es deklariert, also ist $this->pin im Kind eine undefinierte Eigenschaft (eine Warnung, dann null), und eine Methode des Kindes mit demselben Namen überschreibt keine private. Deklariere das Member als protected, wenn Kindklassen es brauchen.

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

LOS GEHT'S