Astrazione delle classi

PHP 5 introduce classi e metodi astratti. Le classi definite come astratte non possono essere istanziate, e qualsiasi classe che contenga almeno un metodo astratto deve anch'essa essere astratta. I metodi definiti come astratti dichiarano unicamente la propria firma - non possono dichiarare un'implementazione.

Quando ereditati da una classe astratta, tutti i metodi segnalati come astratti nella dichiarazione della classe padre devono essere definiti dalla classe figlio; inoltre, questi metodi devono essere definiti con la stessa or a visibilità (o con una meno ristretta). Per esempio, se il metodo astratto è definito come protetto, l'implementazione della funzione può essere definita come protetta o publica, ma non privata. Inoltre le firme dei metodi devono corrispondere, cioè il tipo e il numero degli argomenti richiesti deve essere lo stesso. Per esempio, se la classe figlio definisce un argomento opzionale, mentre la firma del metodo astratto non lo fa, non ci sono conflitti nella firma. Questo vale anche per i costruttori a partire da PHP 5.4. Prima della 5.4 le firme dei costruttori possono essere differenti.

Example #1 Esempio di classe astratta

<?php
abstract class AbstractClass
{
// Forza la classe estendente a definire questo metodo
abstract protected function getValue();
abstract protected function
prefixValue($prefix);

// Metodi comuni
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";
?>

Il precedente esempio visualizzerà:

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

Example #2 Abstract class example

<?php
abstract class AbstractClass
{
// Il nostro metodo astratto ha solo bisogno di definire gli argomenti richiesti
abstract protected function prefixName($name);

}

class
ConcreteClass extends AbstractClass
{

// La nostra classe figlio può definire argomenti opzionali non presenti nella firma del padre
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";
?>

Il precedente esempio visualizzerà:

Mr. Pacman
Mrs. Pacwoman

Codice vecchio che non ha classi definite dall'utente o funzioni dichiarate come 'abstract' dovrebbe poter essere eseguito senza necessità di modifiche.