Skip to content

6. Interfaces

Een interface is een structuur die prototypes van methoden definieert. Een klasse die een interface implementeert, moet de code van alle methoden van de interface definiëren.

6.1. De scriptboomstructuur

Image

6.2. Een eerste interface

We definiëren een interface [IExemple] in een script [IExemple.php]. In datzelfde script definiëren we twee klassen die de interface [IExemple] implementeren:


<?php

// strikte naleving van de typen van de functieparameters
declare(strict_types=1);

// naamruimte
namespace Exemples;

// een interface
interface IExemple {
    // de methoden van de interface
    public function ajouter(int $i, int $j): int;
    public function soustraire(int $i, int $j): int;
}

// implementatie 1 van de interface IExemple
class Classe1 implements IExemple {
    public function ajouter(int $a, int $b): int {
        return $a + $b + 10;
    }

    public function soustraire(int $a, int $b): int {
        return $a - $b + 20;
    }

}

// implementatie 2 van de interface IExemple
class Classe2 implements IExemple {
    public function ajouter(int $a, int $b) : int{
        return $a + $b + 100;
    }

    public function soustraire(int $a, int $b) : int {
        return $a - $b + 200;
    }

}

Opmerkingen

  • regels 10-14: de interface IExemple definieert twee methoden: de functie ajouter (regel 12) en de functie soustraire (regel 13). De interface definieert de code van deze methoden niet. Dit wordt gedaan door de klassen die de interface implementeren;
  • regel 17: de klasse Classe1 implementeert de interface IExemple. Zij definieert dus een code voor de methoden ajouter (regel 18) en soustraire (regel 22);
  • regels 29-38: hetzelfde geldt voor de klasse Classe2;

We gebruiken de interface [IExemple] in het volgende script [interfaces-01.php]:


<?php

require_once "IExemple.php";
use \Exemples\Classe1;
use \Exemples\Classe2;
use \Exemples\IExemple;

// functie
function calculer(int $a, int $b, IExemple $interface) : void {
  print $interface->ajouter($a, $b)."\n";
  print $interface->soustraire($a, $b)."\n";
}

// ------------------- main
// aanmaken van 2 objecten van het type Klasse1 en Klasse2
$c1 = new Classe1();
$c2 = new Classe2();
// de functie berekenen aanroepen
calculer(4, 3, $c1);
calculer(14, 13, $c2);

Opmerkingen

  • regels 3-6: opname en definitie van de klassen en interfaces die door het script worden gebruikt;
  • regel 3: in plaats van de instructie include hebben we hier de instructie require_once gebruikt. De `include`-instructie voegt een bestand toe aan het huidige script, zelfs als dit al is opgenomen, terwijl de instructie `require_once` het slechts één keer opneemt. Wat het opnemen van code betreft, geven we dus de voorkeur aan de instructie `require_once`;
  • regels 9-12: we definiëren een functie;
  • regel 9: hier hebben we het type van de drie parameters gedeclareerd. Als de daadwerkelijke parameter tijdens de uitvoering niet van het verwachte type is, wordt er een fout gegenereerd. De derde parameter is van het type [IExemple]. Dit betekent dat de daadwerkelijke parameter een instantie moet zijn van een klasse die de interface [IExemple] implementeert, dus in ons voorbeeld een instantie van de klassen [Classe1] of [Classe2];
  • regels 10-11: we gebruiken de methoden [ajouter, soustraire] van de interface [IExemple];
  • regel 19: de derde effectieve parameter is van het type [Classe1], compatibel met het type [IExemple] van de derde formele parameter van de functie;
  • regel 20: idem voor de klasse [Classe2];

Resultaten

1
2
3
4
17
21
127
201

6.3. Afleiding van een interface

Net zoals een dochterklasse een bovenliggende klasse kan uitbreiden, kan een dochterinterface een bovenliggende interface uitbreiden.

Laten we eens kijken naar de interface [IExemple2] die is gedefinieerd in het bestand [IExemple2.php]:


<?php

// strikte naleving van de typen van de functieparameters
declare(strict_types=1);
// naamruimte
namespace Exemples;

// opname van de definitie van de interface IExemple
require_once __DIR__."/IExemple.php";

// een interface die is afgeleid van IExemple
interface IExemple2 extends IExemple {
    // de methode van de interface
    public function multiplier(int $i, int $j): int;
}

// implementatie van de interface IExemple2
class Classe3 extends Classe2 implements IExemple2 {
   
    public function multiplier(int $a, int $b): int {
        return $a * $b;
    }

}

Opmerkingen

  • regel 6: de interface [IExemple2] bevindt zich in dezelfde naamruimte als de interface [Iexemple];
  • regel 9: het definitiebestand van de interface [Iexemple] wordt opgenomen;
  • regels 12-15: definiëren de interface [IExemple2], die de interface [Iexemple] uitbreidt (erft) en er een nieuwe methode aan toevoegt (regel 14);
  • regels 18-24: de klasse [Classe3] is een uitbreiding van de klasse [Classe2]. Aangezien deze de interface [IExemple] implementeert, geldt dit ook voor de klasse [Classe3]. [Classe3] erft namelijk alle openbare en beschermde methoden van de klasse [Classe2], dus ook de methoden ‘toevoegen’ en ‘aftrekken’. Bovendien wordt aangegeven dat [Classe3] de interface [IExemple2] implementeert. Als zodanig moet deze ook de methode ‘vermenigvuldigen’ implementeren, wat [Classe2] niet doet. Dit gebeurt in de regels 20-22;

De interface [IExemple2] wordt gebruikt door het volgende script [interfaces-02]:


<?php

// strikte naleving van de typen van de functieparameters
declare(strict_types=1);

// opname en kwalificaties van de klassen en interfaces die nodig zijn voor het script
require_once __DIR__."/Iexemple2.php";
use \Exemples\IExemple2;
use \Exemples\Classe3;

// functie
function calculer(int $a, int $b, IExemple2 $interface) {
    print $interface->ajouter($a, $b) . "\n";
    print $interface->soustraire($a, $b) . "\n";
    print $interface->multiplier($a, $b) . "\n";
}

// ------------------- main
// aanmaken van 1 object van het type Klasse3 dat IExemple2 implementeert
$c3 = new Classe3();
// de functie ‘berekenen’ aanroepen
calculer(4, 3, $c3);

Opmerkingen

  • regel 12: de derde parameter van de functie [calculer] is van het type [IExemple2];
  • regels 13-15: we gebruiken de drie methoden van de interface [IExemple2];
  • regel 22: de functie [calculer] wordt aangeroepen met als derde parameter een object van het type [IExemple2] (regel 20);

Resultaten

1
2
3
107
201
12

6.4. Een interface als parameter van een functie doorgeven

In de vorige paragraaf hebben we gezien dat wanneer het verwachte type voor een functieparameter een klasse is, de daadwerkelijke parameter een object van het verwachte type of een afgeleid type kan zijn. Hetzelfde geldt voor interfaces, zoals blijkt uit het volgende script [interfaces-03.php]:


<?php

// strikte naleving van de typen van de functieparameters
declare(strict_types=1);

// opname en kwalificaties van de klassen en interfaces die nodig zijn voor het script
require_once __DIR__."/IExemple.php";
use \Exemples\IExemple;
require_once __DIR__."/IExemple2.php";
use \Exemples\Classe3;

// functie
function calculer(int $a, int $b, IExemple $interface) {
  print $interface->ajouter($a, $b) . "\n";
  print $interface->soustraire($a, $b) . "\n";
}

// ------------------- main
// aanmaken van 1 object van het type Klasse3 dat IExemple2 implementeert en dus ook IExemple
$c3 = new Classe3();
// de functie ‘berekenen’ aanroepen
calculer(4, 3, $c3);

Opmerkingen

  • regel 13: de functie [calculer] verwacht als derde parameter een type [IExemple]. Dit betekent dat het type van de daadwerkelijke parameter van het type [IExemple] of een afgeleid type kan zijn;
  • regel 20: er wordt een object $c3 geïnstantieerd van het type [Classe3], een klasse die de interface [IExemple2] implementeert, die op haar beurt de interface [IExemple] uitbreidt. Dus uiteindelijk implementeert $c3 de interface [IExemple];
  • regel 22: de functie [calculer] wordt aangeroepen met als derde parameter een object $c3 van het type [Classe3]. Door het spel van klasse-overerving en implementaties hebben we gezien dat het object $c3 het type [IExemple] implementeert. We kunnen het dus als derde parameter gebruiken;

Resultaten

107
201