Skip to content

6. Interfaces

An interface is a structure that defines method prototypes. A class that implements an interface must define the code for all of the interface’s methods.

6.1. The script tree

Image

6.2. A first interface

We define an interface [IExample] in a script [IExample.php]. In this same script, we define two classes that implement the [IExample] interface:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// namespace
namespace Exemples;
 
// an interface
interface IExemple {
    // interface methods
    public function ajouter(int $i, int $j): int;
    public function soustraire(int $i, int $j): int;
}
 
// implementation 1 of the IExemple interface
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;
    }
 
}
 
// implementation 2 of the IExemple interface
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;
    }
 
}

Comments

  • lines 10–14: The IExample interface defines two methods: the add function (line 12) and the subtract function (line 13). The interface does not define the code for these methods. The classes that implement the interface will do so;
  • line 17: The Class1 class implements the IExample interface. It therefore defines code for the add method (line 18) and the subtract method (line 22);
  • lines 29–38: same for the Class2 class;

We use the [IExemple] interface in the following [interfaces-01.php] script:


<?php
 
require_once "IExemple.php";
use \Exemples\Classe1;
use \Exemples\Classe2;
use \Exemples\IExemple;
 
// function
function calculer(int $a, int $b, IExemple $interface) : void {
  print $interface->ajouter($a, $b)."\n";
  print $interface->soustraire($a, $b)."\n";
}
 
// ------------------- hand
// creation of 2 objects of type Class1 and Class2
$c1 = new Classe1();
$c2 = new Classe2();
// call the calculate function
calculer(4, 3, $c1);
calculer(14, 13, $c2);

Comments

  • lines 3–6: inclusion and definition of the classes and interfaces used by the script;
  • line 3: instead of the include statement, we have used the require_once statement here. The include statement includes a file in the current script even if it has already been included, whereas the require_once statement includes it only once. Therefore, when it comes to including code, we prefer the require_once statement;
  • Lines 9–12: We define a function;
  • Line 9: Here, we declare the types of the three parameters. If, at runtime, the actual parameter is not of the expected type, an error is thrown. The third parameter is of type [IExample]. This means that the actual parameter must be an instance of a class that implements the [IExample] interface; in our example, this means an instance of the [Class1] or [Class2] classes;
  • Lines 10–11: We use the [add, subtract] methods of the [IExample] interface;
  • line 19: the third actual parameter is of type [Class1], which is compatible with the [IExample] type of the function’s third formal parameter;
  • line 20: same for the [Class2] class;

Results

1
2
3
4
17
21
127
201

6.3. Deriving an Interface

Just as a child class can extend a parent class, a child interface can extend a parent interface.

Consider the [IExample2] interface defined in the [IExample2.php] file:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
// namespace
namespace Exemples;
 
// interface definition IExemple included
require_once __DIR__."/IExemple.php";
 
// an interface derived from IExemple
interface IExemple2 extends IExemple {
    // the interface method
    public function multiplier(int $i, int $j): int;
}
 
// implementation of IExemple2 interface
class Classe3 extends Classe2 implements IExemple2 {
   
    public function multiplier(int $a, int $b): int {
        return $a * $b;
    }
 
}

Comments

  • line 6: the interface [IExample2] will be in the same namespace as the interface [Iexample];
  • line 9: the definition file for the [Iexample] interface is included;
  • lines 12–15: define the interface [IExample2], which extends (inherits from) the interface [IExample] and adds a new method to it (line 14);
  • lines 18–24: the class [Class3] extends the class [Class2]. Since [Class2] implements the interface [IExample], [Class3] will also implement it. In fact, [Class3] inherits all the public and protected methods of the [Class2] class, including the add and subtract methods. Furthermore, we specify that [Class3] implements the [IExample2] interface. As such, it must also implement the multiply method, which [Class2] does not. This is what lines 20–22 do;

The [IExample2] interface is used by the following [interfaces-02] script:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// inclusion and qualification of classes and interfaces required by the script
require_once __DIR__."/Iexemple2.php";
use \Exemples\IExemple2;
use \Exemples\Classe3;
 
// function
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";
}
 
// ------------------- hand
// creation of 1 Class3 object implementing IExemple2
$c3 = new Classe3();
// call the calculate function
calculer(4, 3, $c3);

Comments

  • line 12: the third parameter of the [calculate] function is of type [IExample2];
  • lines 13–15: the three methods of the [IExample2] interface are used;
  • line 22: the [calculate] function is called with an object of type [IExample2] as the third parameter (line 20);

Results

1
2
3
107
201
12

6.4. Passing an Interface as a Function Parameter

We saw in the previous section that when the expected type for a function parameter is a class, the actual parameter can be an object of the expected type or a derived type. The same applies to interfaces, as shown in the following script [interfaces-03.php]:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// inclusion and qualification of classes and interfaces required by the script
require_once __DIR__."/IExemple.php";
use \Exemples\IExemple;
require_once __DIR__."/IExemple2.php";
use \Exemples\Classe3;
 
// function
function calculer(int $a, int $b, IExemple $interface) {
  print $interface->ajouter($a, $b) . "\n";
  print $interface->soustraire($a, $b) . "\n";
}
 
// ------------------- hand
// creation of 1 object of type Class3 which implements IExemple2 and therefore IExemple
$c3 = new Classe3();
// call the calculate function
calculer(4, 3, $c3);

Comments

  • line 13: the [calculate] function expects a type [IExample] as its third parameter. This means that the actual parameter type can be [IExample] or a derived type;
  • line 20: we instantiate an object $c3 of type [Class3], a class that implements the interface [IExample2], which itself extends the interface [IExample]. So ultimately, $c3 implements the interface [IExample];
  • line 22: we call the function [calculate] with an object $c3 of type [Class3] as the third parameter. Through the interplay of class inheritance and implementations, we saw that the object $c3 implements the type [IExample]. We can therefore use it as the third parameter;

Results

107
201