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

    ?>

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open