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 Examples;

// an interface
interface IExample {
    // interface methods
    public function add(int $i, int $j): int;
    public function subtract(int $i, int $j): int;
}

// Implementation 1 of the IExample interface
class Class1 implements IExample {
    public function add(int $a, int $b): int {
        return $a + $b + 10;
    }

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

}

// Implementation 2 of the IExample interface
class Class2 implements IExample {
    public function add(int $a, int $b) : int{
        return $a + $b + 100;
    }

    public function subtract(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 \Examples\Class1;
use \Examples\Class2;
use \Examples\IExample;

// function
function calculate(int $a, int $b, IExample $interface) : void {
  print $interface->add($a, $b)."\n";
  print $interface->subtract($a, $b)."\n";
}

// ------------------- main
// Create 2 objects of type Class1 and Class2
$c1 = new Class1();
$c2 = new Class2();
// call the calculate function
calculate(4, 3, $c1);
calculate(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 Examples;

// Include the definition of the IExample interface
require_once __DIR__."/IExample.php";

// an interface that extends IExample
interface IExample2 extends IExample {
    // the interface method
    public function multiply(int $i, int $j): int;
}

// implementation of the IExample2 interface
class Class3 extends Class2 implements IExample2 {
   
    public function multiply(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__."/Iexample2.php";
use \Examples\Example2;
use \Examples\Class3;

// function
function calculate(int $a, int $b, IExample2 $interface) {
    print $interface->add($a, $b) . "\n";
    print $interface->subtract($a, $b) . "\n";
    print $interface->multiply($a, $b) . "\n";
}

// ------------------- main
// Create an object of type Class3 that implements IExample2
$c3 = new Class3();
// call the calculate function
calculate(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__."/IExample.php";
use \Examples\IExample;
require_once __DIR__."/IExample2.php";
use \Examples\Class3;

// function
function calculate(int $a, int $b, IExample $interface) {
  print $interface->add($a, $b) . "\n";
  print $interface->subtract($a, $b) . "\n";
}

// ------------------- main
// Create an object of type Class3 that implements IExample2 and therefore IExample
$c3 = new Class3();
// call the calculate function
calculate(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