Klassenabstraktion

PHP 5 führt abstrakte Klassen und Methoden ein. Abstrakt definierte Klassen dürfen nicht instanziiert werden. Jede Klasse, die wenigstens eine abstrakte Methode enthält, muss ebenso abstrakt sein. Abstrakt definierte Methoden deklarieren nur die Signatur der Methode - sie können nicht die Implementierung definieren.

Wenn eine abstrakte Klasse abgeleitet wird, müssen alle in der Deklaration der Elternklasse abstrakt bezeichneten Methoden durch das Kind definiert werden. Zusätzlich müssen diese Methoden mit derselben (oder einer weniger einschränkenden) Sichtbarkeit definiert werden. Wenn die abstrakte Methode zum Beispiel als protected definiert ist, muss die Funktionsimplementierung entweder als protected oder public, aber nicht private, definiert sein. Ebenfalls müssen die Methodensignaturen zueinander passen, d.h. die Type Hints und die Anzahl der verpflichtenden Parameter muss gleich sein. Wenn zum Beispiel die Kindklasse einen optionalen Parameter definiert, den die Signatur der abstrakten Methode nicht vorsieht, dann gibt es keinen Konflikt in den Signaturen. Gleiches gilt seit PHP 5.4 für Konstruktoren. Vor 5.4. konnten die Signaturen von Konstruktoren von einander abweichen.

Beispiel #1 Beispiel für abstrakte Klasse

<?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 Abstract class example

<?php
abstract class AbstractClass
{
  
// Unsere abstrakte Methode muss nur die verpflichtenden Parameter definieren
  
abstract protected function prefixName($name);

}

class 
ConcreteClass extends AbstractClass
{
  
// Unsere 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

Älterer Code, der keine nutzerdefinierten Klassen oder Funktionen mit dem Namen 'abstract' besitzt, sollte ohne Änderungen lauffähig sein.