Abstraction de classes

PHP 5 introduit les concepts de classes et de méthodes abstraites. Les classes définies comme abstraites ne peuvent pas être instanciées, et toute classe contenant au moins une méthode abstraite doit elle-aussi être abstraite. Les méthodes définies comme abstraites déclarent simplement la signature de la méthode - elles ne peuvent définir son implémentation.

Lors de l'héritage d'une classe abstraite, toutes les méthodes marquées comme abstraites dans la déclaration de la classe parente doivent être définies par l'enfant ; de plus, ces méthodes doivent être définies avec la même visibilité, ou une visibilité moins restreinte. Par exemple, si la méthode abstraite est définie comme protégée, l'implémentation de la fonction doit être définie comme protégée ou publique, mais pas privée. De plus, les signatures de ces méthodes doivent correspondre, ce qui signifie que les types des paramètres et le nombre d'arguments requis doivent être les mêmes. Par exemple, si la classe enfant définit un argument optionnel, alors que la signature de la méthode abstraite ne le définit pas, il n'y aura aucun conflit dans la signature. Ceci s'applique aussi aux constructeurs depuis PHP 5.4. Avant la version 5.4, les signatures des constructeurs pouvaient être différentes.

Exemple #1 Exemple de classe abstraite

<?php
abstract class AbstractClass 
{
	// Force les classes filles à définir cette méthode
	abstract protected function getValue();
	abstract protected function prefixValue($prefix);

	// méthode commune
	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";
?>
<?php
abstract class AbstractClass
{
	// Notre méthode abstraite ne doit que définir les arguments requis
	abstract protected function prefixName($name);

}

class ConcreteClass extends AbstractClass
{

	// Notre classe enfant peut définir des arguments optionnels non présents dans la signature du parent
	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";
?>

L'exemple ci-dessus va afficher :

Mr. Pacman
Mrs. Pacwoman

L'ancien code qui n'a pas de classe définie par l'utilisateur ou de fonction nommée 'abstract' devrait continuer à fonctionner sans modification.

LoadingChargement en cours