Objekt-Vererbung
Vererbung ist ein gängiges Prinzip der Programmierung und PHP verwendet dieses Prinzip in seinem Objektmodell. Dieses Prinzip beeinflusst die Art und Weise, in der mehrere Klassen und Objekte in Beziehung zueinander stehen.
Wenn zum Beispiel eine Klasse erweitert wird, so erbt die Unterklasse alle Methoden der Sichtbarkeiten public und protected sowie alle Eigenschaften und Konstanten von der Elternklasse. Wenn eine Klasse diese Methoden nicht überschreibt, wird die ursprüngliche Funktionalität beibehalten.
Dies ist nützlich, um Funktionalität zu definieren und zu abstrahieren und erlaubt es, zusätzliche Funktionalität in ähnlichen Objekten zu implementieren, ohne sämtliche gemeinsame Funktionalitäten neu implementieren zu müssen.
Private Methoden einer Elternklasse sind für eine Kindklasse nicht
zugänglich. Folglich können Kindklassen eine private Methode ohne
Berücksichtigung der normalen Vererbungsregeln selbst reimplementieren. Vor
PHP 8.0.0 wurden jedoch die Einschränkungen final
und
static
auf private Methoden angewandt. Ab PHP 8.0.0 ist
die einzige Einschränkung für private Methoden, die erzwungen wird, die die
private final
bei Konstruktoren, da dies ein üblicher
Weg ist, den Konstruktor zu "deaktivieren", wenn stattdessen statische
Fabrikmethoden (factory methods) verwendet werden.
Die Sichtbarkeit von
Methoden, Eigenschaften und Konstanten kann gelockert werden, so kann z. B.
eine protected
Methode als public
markiert werden, aber sie können nicht eingeschränkt werden, indem z. B.
eine public
Eigenschaft als private
markiert wird.
Hinweis:
Wenn Autoloading nicht verwendet wird, so müssen die Klassen definiert werden, bevor sie verwendet werden. Wenn eine Klasse eine andere erweitert, so muss die Elternklasse vor der Kindklasse deklariert werden. Diese Regel gilt für Klassen, die von anderen Klassen und Interfaces erben.
Hinweis:
Es ist nicht erlaubt, eine schreib- und lesbare Eigenschaft mit einer schreibgeschützten Eigenschaft zu überschreiben oder umgekehrt.
<?php
class A {
public int $prop;
}
class B extends A {
// Unzulässig: lesen-schreiben -> nur-lesen
public readonly int $prop;
}
?>
Beispiel #1 Beispiel für Vererbung
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP ist großartig.' . PHP_EOL;
}
}
class Bar extends Foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Ausgabe: 'Foo: baz'
$foo->printPHP(); // Ausgabe: 'PHP ist großartig.'
$bar->printItem('baz'); // Ausgabe: 'Bar: baz'
$bar->printPHP(); // Ausgabe: 'PHP ist großartig.'
?>
Kompatibilität des Rückgabetyps bei internen Klassen
Vor PHP 8.1 haben die meisten internen Klassen oder Methoden ihren Rückgabetyp nicht deklariert und wenn sie erweitert wurden, war jeder Rückgabetyp erlaubt.
Seit PHP 8.1.0 sind die meisten internen Methoden dazu übergegangen, den Typ des Rückgabewertes "vorläufig" zu deklarieren. In diesem Fall muss der Typ des Rückgabewerts einer Methode mit dem des erweiterten Elternteils kompatibel sein, andernfalls wird ein Missbilligungs-Hinweis ausgegeben. Es ist zu beachten, dass eine fehlende explizite Deklaration des Rückgabetyps ebenfalls als Signaturfehler betrachtet wird, und daher zu einer entsprechenden Meldung führt.
Wenn der Rückgabetyp für eine überschreibende Methode aufgrund von
Kompatibilitätsproblemen zwischen PHP-Versionen nicht deklariert werden
kann, kann das Attribut #[ReturnTypeWillChange]
hinzugefügt
werden, um den Missbilligungs-Hinweis zu unterdrücken.
Beispiel #2 Die überschreibende Methode deklariert keinen Rückgabetyp
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier) { return false; }
}
// "Deprecated: Return type of MyDateTime::modify(string $modifier) should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0
?>
Beispiel #3 Die überschreibende Methode deklariert einen falschen Rückgabetyp
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier): ?DateTime { return null; }
}
// "Deprecated: Return type of MyDateTime::modify(string $modifier): ?DateTime should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0
?>
Beispiel #4 Die überschreibende Methode deklariert einen falschen Rückgabetyp ohne Missbilligungs-Hinweis
<?php
class MyDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[ReturnTypeWillChange]
public function modify(string $modifier) { return false; }
}
// Es wird kein Missbilligungs-Hinweis ausgelöst
?>