PHP Tutorial.nl

Word een PHP expert!!!

Home » Classes » Interfaces

Interfaces: ontdek de kracht van het publieke contract

Naast gewone classes en abstracte classes is het ook mogelijk om interfaces te schrijven. 

Een interface is niet meer dan een ‘contract’ waaraan een class of abstracte class moet voldoen. Binnen een interface geef je aan welke publieke functionaliteit je verwacht van een class die de interface implementeert.

Een interface heeft in tegenstelling tot een abstracte class verder geen implementatie. Het bevat alleen definities van publieke functionaliteit.

<?php
interface Workable {
    /**
     *  Defines the method that works.
     */
    public function work();
}

In de bovenstaande interface hebben we een contract dat een ‘Workable’ aangeeft. Elke class die deze interface gebruikt zal de functie work moeten implementeren.

Implementeren van interfaces

Het implementeren van een interface gebeurd door het implements. Het is mogelijk om meerdere interfaces te implementeren. Dit in tegenstelling tot extends bij classes.

class Medewerker implements Workable {

    public function work() {
        return 'Ik ben aan het werk!';
    }

}

Het implementeren van meerdere interfaces

Het is dus ook mogelijk om een class zelf meerdere interfaces te laten implementeren. Zo kan een medewerker zowel een Workable als een Billable persoon zijn.

class Medewerker implements Workable, Billable {

    public function work() {
        return 'Ik ben aan het werk!';
    }

    public function paycheck() {
        return '2000 euro';
    }

}

Naast de functies zelf kan een interface ook parameters afdwingen. Het is wel belangrijk om deze parameters ook daadwerkelijk te implementeren anders zal de class afwijken van het contract en dat kan fouten opleveren.

Interfaces uitbreiden

Het is ook mogelijk om interface een andere een interface te extenden. Op deze manier breid je de interfaces zelf uit qua definitie.

<?php
interface Workable extends Billable {
    /**
     *  Defines the method that works.
     */
    public function work();
}

In het bovenstaande voorbeeld kan de Billable interface bijvoorbeeld een methode als paycheck afdwingen. Op deze manier kun je dus interfaces aan elkaar knopen.

Interfaces afdwingen

In je methodes (en functies) kun je interfaces als argument afdwingen. Het is eigenlijk altijd verstandig om functionaliteit op basis van een interface af te dwingen. Het kan natuurlijk ook op class niveau, maar dat is lastiger uitwisselbaar. Stel dat de class implementatie gaat afwijken, dan moet je dit op alle locaties mogelijk ook wijzigen.

Je wilt daarom liever op basis van een contract werken, want dan hoef je geen rekening te houden met interne functionaliteit en gedrag. Je weet gewoon wat je kan aanroepen en de rest is bijzaak.

class Personeel {
    public function dailyRoutine(Workable $medewerker) {
        echo $medewerker->work();
    }
}

Interface Constants

Interfaces kunnen ook constante waarden definiëren. Dit is bijvoorbeeld nuttig voor het definiëren van vaste waarden die consistent blijven binnen de implementaties van de interface.

<?php
interface Workable {
    const CONSTANTE_WAARDE = 'Waarde';
}

class Medewerker implements Workable {
    public function toonWaarde() {
        echo self::CONSTANTE_WAARDE;
    }
}

$object = new ImplementatieKlasse();
$object->toonWaarde(); // Output: Waarde
?>

Voordelen van Interfaces

Het gebruik van interfaces komt niet zomaar uit de lucht vallen. Er zijn namelijk een aantal voordelen,

1. Scheiding van implementatie en contract. Interfaces definiëren een contract dat klassen moeten volgen, waardoor de implementatie gescheiden blijft van de specificatie.

2. Polymorfisme. Interfaces maken het mogelijk om verschillende klassen op dezelfde manier te behandelen als ze dezelfde interface implementeren. Dit bevordert polymorfisme.

3. Makkelijker Testen. Interfaces maken het eenvoudiger om afhankelijkheden te mocken of te stubs voor te gebruiken tijdens het testen.

Praktisch Gebruik van Interfaces

Interfaces worden vaak gebruikt in design patterns zoals dependency injection, wat helpt bij het maken van flexibele en testbare code.

<?php
interface Logger {
    public function log($bericht);
}

class FileLogger implements Logger {
    public function log($bericht) {
        file_put_contents('log.txt', $bericht.PHP_EOL, FILE_APPEND);
    }
}

class Application {
    private $logger;

    public function __construct(Logger $logger) {
        $this->logger = $logger;
    }

    public function run() {
        $this->logger->log("Applicatie gestart");
    }
}

$logger = new FileLogger();
$app = new Application($logger);
$app->run();
?>