6. As interfaces
Uma interface é uma estrutura que define protótipos de métodos. Uma classe que implementa uma interface deve definir o código de todos os métodos da interface.
6.1. A árvore de scripts

6.2. Uma primeira interface
Definimos uma interface [IExemple] num script [IExemple.php]. Neste mesmo script, definimos duas classes que implementam a interface [IExemple]:
<?php
// respeito rigoroso dos tipos dos parâmetros das funções
declare(strict_types=1);
// espaço de nomes
namespace Exemples;
// uma interface
interface IExemple {
// os métodos da interface
public function ajouter(int $i, int $j): int;
public function soustraire(int $i, int $j): int;
}
// implementação 1 da 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;
}
}
// implementação 2 da 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;
}
}
Comentários
- linhas 10-14: a interface IExemple define dois métodos: a função ajouter (linha 12) e a função soustraire (linha 13). A interface não define o código destes métodos. São as classes que implementam a interface que o farão;
- linha 17: a classe Classe1 implementa a interface IExemple. Por conseguinte, define um código para os métodos ajouter (linha 18) e soustraire (linha 22);
- linhas 29-38: o mesmo se aplica à classe Classe2;
Utilizamos a interface [IExemple] no seguinte script [interfaces-01.php]:
<?php
require_once "IExemple.php";
use \Exemples\Classe1;
use \Exemples\Classe2;
use \Exemples\IExemple;
// função
function calculer(int $a, int $b, IExemple $interface) : void {
print $interface->ajouter($a, $b)."\n";
print $interface->soustraire($a, $b)."\n";
}
// ------------------- main
// criação de 2 objetos do tipo Classe1 e Classe2
$c1 = new Classe1();
$c2 = new Classe2();
// chamada da função «calcular»
calculer(4, 3, $c1);
calculer(14, 13, $c2);
Comentários
- linhas 3-6: inclusão e definição das classes e interfaces utilizadas pelo script;
- linha 3: em vez da instrução «include», utilizámos aqui a instrução «require_once». A instrução «include» inclui um ficheiro no script atual, mesmo que este já tenha sido incluído, enquanto a instrução «require_once» só o inclui uma vez. Por isso, no que diz respeito à inclusão de código, é preferível utilizar a instrução «require_once»;
- linhas 9-12: define-se uma função;
- linha 9: declaramos aqui o tipo dos três parâmetros. Se, durante a execução, o parâmetro efetivo não for do tipo esperado, é lançado um erro. O terceiro parâmetro é do tipo [IExemple]. Isto significa que o parâmetro efetivo deve ser uma instância de uma classe que implemente a interface [IExemple]; portanto, no nosso exemplo, uma instância das classes [Classe1] ou [Classe2];
- linhas 10-11: utilizamos os métodos [ajouter, soustraire] da interface [IExemple];
- linha 19: o terceiro parâmetro efetivo é do tipo [Classe1], compatível com o tipo [IExemple] do terceiro parâmetro formal da função;
- linha 20: o mesmo se aplica à classe [Classe2];
Resultados
6.3. Derivação de uma interface
Da mesma forma que uma classe filha pode herdar de uma classe pai, uma interface filha pode herdar de uma interface pai.
Consideremos a interface [IExemple2] definida no ficheiro [IExemple2.php]:
<?php
// respeito rigoroso pelos tipos dos parâmetros das funções
declare(strict_types=1);
// espaço de nomes
namespace Exemples;
// inclusão da definição da interface IExemple
require_once __DIR__."/IExemple.php";
// uma interface que deriva de IExemple
interface IExemple2 extends IExemple {
// o método da interface
public function multiplier(int $i, int $j): int;
}
// implementação da interface IExemple2
class Classe3 extends Classe2 implements IExemple2 {
public function multiplier(int $a, int $b): int {
return $a * $b;
}
}
Comentários
- linha 6: a interface [IExemple2] estará no mesmo espaço de nomes que a interface [Iexemple];
- linha 9: inclui-se o ficheiro de definição da interface [Iexemple];
- linhas 12-15: definem a interface [IExemple2], que estende (herda) a interface [Iexemple] e lhe adiciona um novo método (linha 14);
- linhas 18-24: a classe [Classe3] estende a classe [Classe2]. Como esta implementa a interface [IExemple], o mesmo se aplica à classe [Classe3]. Com efeito, a [Classe3] herda todos os métodos públicos e protegidos da classe [Classe2], incluindo, portanto, os métodos «adicionar» e «subtrair». Além disso, indica-se que a classe [Classe3] implementa a interface [IExemple2]. Nessa qualidade, deve também implementar o método «multiplicar», o que a classe [Classe2] não faz. É isso que as linhas 20-22 fazem;
A interface [IExemple2] é utilizada pelo seguinte script [interfaces-02]:
<?php
// respeito rigoroso pelos tipos dos parâmetros das funções
declare(strict_types=1);
// inclusão e qualificações das classes e interfaces necessárias ao script
require_once __DIR__."/Iexemple2.php";
use \Exemples\IExemple2;
use \Exemples\Classe3;
// função
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
// criação de 1 objeto do tipo Classe3 que implementa IExemple2
$c3 = new Classe3();
// chamada à função «calcular»
calculer(4, 3, $c3);
Comentários
- linha 12: o terceiro parâmetro da função [calculer] é do tipo [IExemple2];
- linhas 13-15: utilizam-se os três métodos da interface [IExemple2];
- linha 22: chama-se a função [calculer] com, como terceiro parâmetro, um objeto do tipo [IExemple2] (linha 20);
Resultados
6.4. Passagem de uma interface como parâmetro de uma função
Vimos no parágrafo anterior que, quando o tipo esperado para um parâmetro de função é uma classe, o parâmetro efetivo pode ser um objeto do tipo esperado ou derivado. O mesmo se aplica às interfaces, como mostra o seguinte script [interfaces-03.php]:
<?php
// respeito rigoroso pelos tipos dos parâmetros das funções
declare(strict_types=1);
// inclusão e qualificações das classes e interfaces necessárias ao script
require_once __DIR__."/IExemple.php";
use \Exemples\IExemple;
require_once __DIR__."/IExemple2.php";
use \Exemples\Classe3;
// função
function calculer(int $a, int $b, IExemple $interface) {
print $interface->ajouter($a, $b) . "\n";
print $interface->soustraire($a, $b) . "\n";
}
// ------------------- main
// criação de 1 objeto do tipo Classe3 que implementa IExemple2 e, portanto, IExemple
$c3 = new Classe3();
// chamada à função «calcular»
calculer(4, 3, $c3);
Comentários
- na linha 13, a função [calculer] espera, como terceiro parâmetro, um tipo [IExemple]. Isto significa que o tipo do parâmetro efetivo poderá ser do tipo [IExemple] ou derivado;
- linha 20: instanciamos um objeto $c3 do tipo [Classe3], classe que implementa a interface [IExemple2], que por sua vez estende a interface [IExemple]. Portanto, em última análise, $c3 implementa a interface [IExemple];
- linha 22: chama-se a função [calculer] com, como terceiro parâmetro, um objeto $c3 do tipo [Classe3]. Através da herança de classes e das implementações, verificámos que o objeto $c3 implementava o tipo [IExemple]. Por isso, podemos utilizá-lo como terceiro parâmetro;
Resultados