PHP interfacce


Esempio

introduzione

Le interfacce sono definizioni delle API pubbliche che le classi devono implementare per soddisfare l'interfaccia. Funzionano come "contratti", specificando cosa fa un insieme di sottoclassi, ma non come lo fanno.

La definizione dell'interfaccia è molto simile alla definizione della classe, cambiando la class parola chiave per l' interface :

interface Foo {

}

Le interfacce possono contenere metodi e / o costanti, ma non attributi. Le costanti dell'interfaccia hanno le stesse restrizioni delle costanti di classe. I metodi di interfaccia sono implicitamente astratti:

interface Foo {
    const BAR = 'BAR';

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

Nota: le interfacce non devono dichiarare costruttori o distruttori, poiché si tratta di dettagli di implementazione a livello di classe.

Realizzazione

Qualsiasi classe che deve implementare un'interfaccia deve farlo utilizzando la parola chiave implements . Per fare ciò, la classe deve fornire un'implementazione per ogni metodo dichiarato nell'interfaccia, rispettando la stessa firma.

Una singola classe può implementare più di un'interfaccia alla volta.

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) {
        // ...
    }
}

Quando le classi astratte implementano le interfacce, non hanno bisogno di implementare tutti i metodi. Qualsiasi metodo non implementato nella classe base deve quindi essere implementato dalla classe concreta che lo estende:

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) {
        // ...
    }
}

Si noti che la realizzazione dell'interfaccia è una caratteristica ereditata. Quando si estende una classe che implementa un'interfaccia, non è necessario ridichiarla nella classe concreta, perché è implicita.

Nota: prima di PHP 5.3.9, una classe non poteva implementare due interfacce che specificavano un metodo con lo stesso nome, poiché ciò avrebbe causato ambiguità. Le versioni più recenti di PHP consentono questo finché i metodi duplicati hanno la stessa firma [1] .

Eredità

Come le classi, è possibile stabilire una relazione di ereditarietà tra le interfacce, utilizzando le stesse extends parole chiave. La differenza principale è che l'ereditarietà multipla è consentita per le interfacce:

interface Foo {

}

interface Bar {

}

interface Baz extends Foo, Bar {

}

Esempi

Nell'esempio seguente abbiamo una semplice interfaccia di esempio per un veicolo. I veicoli possono andare avanti e indietro.

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() {
        ...
    }

    ...
}

Quindi creiamo due classi che implementano l'interfaccia: bici e auto. Bici e auto internamente sono molto diverse, ma entrambi sono veicoli e devono implementare gli stessi metodi pubblici forniti da VehicleInterface.

Typehinting consente a metodi e funzioni di richiedere interfacce. Supponiamo di avere una classe di garage, che contiene veicoli di ogni tipo.

class ParkingGarage {
    protected $vehicles = [];

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

Poiché addVehicle richiede un $vehicle di tipo VehicleInterface - non un'implementazione concreta - possiamo inserire sia Bikes che Cars, che ParkingGarage può manipolare e utilizzare.