PHP Interfaces


Exemple

introduction

Les interfaces sont des définitions des API publiques que les classes doivent implémenter pour satisfaire l'interface. Ils fonctionnent comme des "contrats", en spécifiant ce que fait un ensemble de sous-classes, mais pas comment ils le font.

La définition d'interface est très proche de la définition de classe, transformant la class mots-clés en interface :

interface Foo {

}

Les interfaces peuvent contenir des méthodes et / ou des constantes, mais aucun attribut. Les constantes d'interface ont les mêmes restrictions que les constantes de classe. Les méthodes d'interface sont implicitement abstraites:

interface Foo {
    const BAR = 'BAR';

    public function doSomething($param1, $param2);
}

Remarque: les interfaces ne doivent pas déclarer de constructeurs ou de destructeurs, car ce sont des détails d'implémentation au niveau de la classe.

La concrétisation

Toute classe devant implémenter une interface doit le faire en utilisant le mot-clé implements . Pour ce faire, la classe doit fournir une implémentation pour chaque méthode déclarée dans l'interface, en respectant la même signature.

Une seule classe peut implémenter plusieurs interfaces à la fois.

interface Foo {
    public function doSomething($param1, $param2);
}

interface Bar {
    public function doAnotherThing($param1);
}


class Baz implements Foo, Bar {
    public function doSomething($param1, $param2) {
        // ...
    }

    public function doAnotherThing($param1) {
        // ...
    }
}

Lorsque les classes abstraites implémentent des interfaces, elles n'ont pas besoin d'implémenter toutes les méthodes. Toute méthode non implémentée dans la classe de base doit alors être implémentée par la classe concrète qui l'étend:

abstract class AbstractBaz implements Foo, Bar {
    // Partial implementation of the required interface...
    public function doSomething($param1, $param2) {
        // ...
    }
}

class Baz extends AbstractBaz {
    public function doAnotherThing($param1) {
        // ...
    }
}

Notez que la réalisation de l'interface est une caractéristique héritée. Lors de l'extension d'une classe qui implémente une interface, il n'est pas nécessaire de la redéclarer dans la classe concrète, car elle est implicite.

Note: Avant PHP 5.3.9, une classe ne pouvait pas implémenter deux interfaces spécifiant une méthode avec le même nom, car cela provoquerait une ambiguïté. Les versions plus récentes de PHP permettent cela tant que les méthodes en double ont la même signature [1] .

Héritage

Comme les classes, il est possible d'établir une relation d'héritage entre les interfaces, en utilisant le même mot extends clé extends . La principale différence est que l'héritage multiple est autorisé pour les interfaces:

interface Foo {

}

interface Bar {

}

interface Baz extends Foo, Bar {

}

Exemples

Dans l'exemple ci-dessous, nous avons un exemple simple d'interface pour un véhicule. Les véhicules peuvent avancer et reculer.

interface VehicleInterface {
    public function forward();

    public function reverse();

    ...
}

class Bike implements VehicleInterface {
    public function forward() {
        $this->pedal();
    }

    public function reverse() {
        $this->backwardSteps();
    }

    protected function pedal() {
        ...
    }

    protected function backwardSteps() {
        ...
    }

    ...
}

class Car implements VehicleInterface {
    protected $gear = 'N';

    public function forward() {
        $this->setGear(1);
        $this->pushPedal();
    }

    public function reverse() {
        $this->setGear('R');
        $this->pushPedal();
    }

    protected function setGear($gear) {
        $this->gear = $gear;
    }

    protected function pushPedal() {
        ...
    }

    ...
}

Ensuite, nous créons deux classes qui implémentent l'interface: Bike et Car. Bike and Car en interne sont très différents, mais les deux sont des véhicules et doivent implémenter les mêmes méthodes publiques que VehicleInterface.

Typehinting permet aux méthodes et fonctions de demander des interfaces. Supposons que nous ayons une classe de parking qui contient des véhicules de toutes sortes.

class ParkingGarage {
    protected $vehicles = [];

    public function addVehicle(VehicleInterface $vehicle) {
        $this->vehicles[] = $vehicle;
    }
}

Comme addVehicle nécessite un $vehicle de type VehicleInterface pas d'implémentation concrète), nous pouvons entrer Bikes et Cars, que le ParkingGarage peut manipuler et utiliser.