POO, classe abstraite
Une classe abstraite est une classe qui ne peut pas être instanciée, et toute classe qui contient une méthode abstraite doit être abstraite.
abstract class Animaux {
abstract public function seDeplacer();
}
Cependant, une classe abstraite n’est pas obligée d’avoir que des méthodes abstraites. Elle peut contenir par exemple un constructeur. Une méthode abstraite est une méthode vide (qui n’est donc pas codée), comme la méthode seDeplacer() ci-dessous.
abstract class Animaux {
public function __construct() {
echo "C'est un animal";
}
abstract public function seDeplacer();
}
A quoi ça sert?
Une classe abstraite force les classes qui la dérivent à implémenter des fonctions aux modes d’accès public ou protégé. Autrement dit, dans l’exemple ci-dessus, les classes qui héritent de la classe mère devront implémenter obligatoirement la méthode seDeplacer().
abstract class Animaux {
public function __construct() {
echo "C'est un animal";
}
abstract public function seDeplacer();
}
class Chien extends Animaux {
public function seDeplacer() {
echo 'le chien se déplace à quatres pattes';
}
}
$milou = new Chien;
echo '<br>';
$milou->seDeplacer();
Affichage
C'est un animal
Le chien se déplace à quatres pattes
Une classe abstraite oblige donc les classes dérivées à avoir les mêmes fonctionnalités, elle force l’héritage : ‘Si tu veux être comme moi tu dois faire comme moi’.
Si la classe qui dérive ne contient pas la méthode seDeplacer, PHP retournera une erreur fatale.
abstract class Animaux {
public function __construct() {
echo "C'est un animal";
}
abstract public function seDeplacer();
}
class Chien extends Animaux {
// méthode non implémentée
}
$milou = new Chien;
echo '<br>';
$milou->seDeplacer();
Affichage
Fatal error: Class Chien contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Animaux::seDeplacer)
Visibilité
La visibilité des méthodes de la classe qui dérive doit être la même ou moindre que celle des méthodes abstraites de la classe abstraite, sinon PHP retourne une erreur fatale.
abstract class Animaux {
public function __construct() {
echo "C'est un animal";
}
abstract public function seDeplacer();
}
class Chien extends Animaux {
protected function seDeplacer() { // visibilité SUPERIEUR qui génère une erreur fatale
echo 'Le chien se déplace à quatres pattes';
}
}
Affichage
Fatal error: Access level to Chien::seDeplacer() must be public (as in class Animaux)
Interface
L’interface diffère de la classe abstraite puisque qu’en soit ce n’est pas une classe : on ne peut donc ni l’instancier, ni l’hériter. Mais elle ressemble à la classe abstraite parce qu’on retrouve cette notion de contrainte : obligation d’implémenter ses méthodes.
La création d’une interface se fait avec la syntaxe interface
interface ActionDeVoler {
public function voler();
}
Il est possible de créer plusieurs autres fonctions à une interface. Note : les méthodes d’une interface sont toujours en mode d’accès public.
L’utilisation d’une interface se fait avec la syntaxe implements
interface ActionDeVoler {
public function voler();
}
// class abstraite
abstract class Animaux {
public function __construct() {
echo "C'est un animal";
}
abstract public function seDeplacer();
}
// héritage avec implémentation de l'interface
class Oiseau extends Animaux implements ActionDeVoler {
public function seDeplacer() { // visibilité SUPERIEUR qui génère une erreur fatale
echo 'Un oiseau se déplace en volant';
}
public function voler(){
echo "Un oiseau vole comme un avion";
}
}
$pigeon = new Oiseau;
echo '<br>';
$pigeon->seDeplacer();
echo '<br>';
$pigeon->voler();
Affichage
C'est un animal
Un oiseau se déplace en volant
Un oiseau vole comme un avion
Explication
Dans cette exemple, la classe abstraite est créée pour imposer aux héritiers la méthode seDeplacer(). En effet un oiseau est un animal qui se déplace. Vous remarquer que seuls les héritiers peuvent implémenter la fonction seDeplacer() puisque qu’elle est définie dans une classe abstraite.
L’intérêt de l’interface est qu’elle peut être réutiliser par tout autre classe puisque qu’elle s’implémente au niveau de la classe et non pas à l’intérieur de celle-ci. Dans notre exemple, la fonction voler peut être implémenter par la classe Oiseau mais elle pourrait aussi être associée à une classe Avion, comme illustré dans l’exemple ci-dessous.
interface ActionDeVoler {
public function voler();
}
// class abstraite animaux
abstract class Animaux {
public function __construct() {
echo "C'est un animal";
}
abstract public function seDeplacer();
}
// héritage avec implémentation de l'interface
class Oiseau extends Animaux implements ActionDeVoler {
public function seDeplacer() { // visibilité SUPERIEUR qui génère une erreur fatale
echo 'Un oiseau se déplace en volant';
}
public function voler(){
echo "Un oiseau avec ses plumes";
}
}
// class abstraite avion
abstract class Avion {
public function __construct() {
echo "C'est un avion";
}
abstract public function seDeplacer();
}
// héritage avec implémentation de l'interface
class Drone extends Avion implements ActionDeVoler {
public function seDeplacer() { // visibilité SUPERIEUR qui génère une erreur fatale
echo 'Le drone se déplace en volant';
}
public function voler(){
echo "je vole avec des hélices";
}
}
$pigeon = new Oiseau;
echo '<br>';
$pigeon->seDeplacer();
echo '<br>';
$pigeon->voler();
echo '<br>';
$drone = new Drone;
echo '<br>';
$drone->seDeplacer();
echo '<br>';
$drone->voler();
Affichage
C'est un animal
Un oiseau se déplace en volant
Un oiseau vole comme un avion
C'est un avion
Un drone se déplace en volant
Un drone vole avec des hélices