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:

Mr. Pacman
Mrs. Pacwoman

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;
}
}
}

?>