Klassenabstraktion
PHP unterstützt abstrakte Klassen und Methoden. Abstrakt definierte Klassen
können nicht instantiiert werden. Jede Klasse, die wenigstens eine abstrakte
Methode oder Eigenschaft enthält, muss ebenso abstrakt sein. Als abstrakt
definierte Methoden deklarieren nur die Signatur der Methode und ob sie
öffenlich oder geschützt ist - sie können nicht die Implementierung
definieren. Als abstrakt definierte Eigenschaften können eine Anforderung
für das Verhalten von get
oder set
deklarieren und eine Implementierung für eine, aber nicht für beide
Operationen bereitstellen.
Wenn von einer abstrakten Klasse abgeleitet wird, müssen alle in der Deklaration
der Elternklasse als abstrakt bezeichneten Methoden durch das Kind definiert
werden und den üblichen Regeln zur
Vererbung und
Signatur-Kompatibilität folgen.
Seit PHP 8.4 kann eine abstrakte Klasse eine abstrakte Eigenschaft
deklarieren, die entweder öffenlich oder geschützt ist.
Eine abstrakte Eigenschaft, die geschützt ist, kann durch eine Eigenschaft
erfüllt werden, die entweder vom geschützten oder vom öffenlichen
Geltungsbereich aus lesbar/schreibbar ist
Eine abstrakte Eigenschaft kann entweder durch eine Standardeigenschaft oder
durch eine Eigenschaft mit definierten
Hooks erfüllt werden,
die der erforderlichen Operation entspricht.
Beispiel #1 Beispiel für eine abstrakte Methode
<?php
abstract class AbstractClass
{
// Die abgeleitete Klasse zwingen, diese Methoden zu definieren
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Gemeinsame Methode
public function printOut()
{
print $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue()
{
return "ConcreteClass1";
}
public function prefixValue($prefix)
{
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue()
{
return "ConcreteClass2";
}
public function prefixValue($prefix)
{
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1();
$class1->printOut();
echo $class1->prefixValue('FOO_'), "\n";
$class2 = new ConcreteClass2();
$class2->printOut();
echo $class2->prefixValue('FOO_'), "\n";
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2
Beispiel #2 Beispiel für eine abstrakte Methode
<?php
abstract class AbstractClass
{
// Eine abstrakte Methode muss nur die verpflichtenden Parameter definieren
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// Eine Kindklasse kann optionale Parameter definieren, die sich nicht in der
// Signatur der Elternklasse wiederfinden
public function prefixName($name, $separator = ".")
{
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass();
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
Beispiel #3 Beispiel für eine abstrakte Eigenschaft
<?php
abstract class A
{
// Erweiternde Klassen müssen eine öffentlich lesbare Eigenschaft haben
abstract public string $readable {
get;
}
// Erweiternde Klassen müssen eine geschützt oder öffentlich schreibbare
// Eigenschaft haben
abstract protected string $writeable {
set;
}
// Erweiternde Klassen müssen eine geschützte oder öffentliche symmetrische
// Eigenschaft haben
abstract protected string $both {
get;
set;
}
}
class C extends A
{
// Dies erfüllt die Anforderung und macht sie außerdem einstellbar, was
// gültig ist
public string $readable;
// Dies würde die Anforderung NICHT erfüllen, da sie nicht öffentlich
// lesbar ist
protected string $readable;
// Dies erfüllt die Anforderung genau, ist also ausreichend.
// Es darf nur geschrieben werden, und zwar nur aus dem geschützten Bereich
protected string $writeable {
set => $value;
}
// Dies erweitert die Sichtbarkeit von geschützt auf öffentlich, was in
// Ordnung ist
public string $both;
}
?>
Eine abstrakte Eigenschaft einer abstrakten Klasse kann Implementierungen
für jeden Hook bereitstellen, muss aber entweder get
oder
set
deklariert, aber nicht definiert haben (wie im obigen
Beispiel).
Beispiel #4 Beispiel für eine abstrakte Eigenschaft mit Hooks
<?php
abstract class A
{
// Dies bietet eine vorgegebene (aber überschreibbare) set-Implementierung
// und erfordert, dass Kindklassen eine get-Implementierung bereitstellen
abstract public string $foo {
get;
set {
$this->foo = $value;
}
}
}
?>