W3docs

Programação Orientada a Objetos com Interfaces PHP

Aprenda a declarar e implementar interfaces PHP em OOP, usar constantes, estender interfaces e evitar erros comuns.

Uma interface é um contrato que lista os métodos que uma classe deve fornecer, sem dizer como esses métodos funcionam. Ela permite que classes não relacionadas concordem com um conjunto compartilhado de comportamentos, de modo que o restante do seu código possa depender do contrato e não de uma classe específica. Este capítulo aborda como declarar interfaces, implementá-las, usar constantes, estender e combinar interfaces, e os erros comuns a evitar.

Se você é novo em objetos, leia primeiro Classes e Objetos PHP e O que é OOP em PHP.

O que é uma Interface em PHP?

Uma interface define um conjunto de assinaturas de métodos públicos — nomes, parâmetros e (opcionalmente) tipos de retorno — mas sem corpo para os métodos. Qualquer classe que implementa a interface promete fornecer um corpo concreto para cada um desses métodos. Se não o fizer, o PHP lança um erro fatal.

Como a interface apenas define o que uma classe pode fazer e nunca como, você pode trocar uma implementação por outra sem modificar o código que as utiliza. Esse desacoplamento é o objetivo principal.

<?php
interface Logger {
  public function log(string $message): void;
}

Regras principais para membros de interface:

  • Todos os métodos são implicitamente públicos e abstratos — você não pode dar-lhes corpos, e não pode marcá-los como private ou protected.
  • Uma interface pode declarar constantes, mas não propriedades.
  • Uma classe sinaliza que cumpre o contrato com a palavra-chave implements.

Por que Usar Interfaces?

  • Contratos. Garantem que qualquer classe implementadora exponha uma API acordada, para que os chamadores saibam exatamente quais métodos estão disponíveis.
  • Baixo acoplamento. O código pode ser escrito contra a interface (Logger) em vez de uma classe concreta (FileLogger), permitindo trocar implementações livremente — um logger de arquivo real em produção, um falso nos testes.
  • Múltiplos tipos. Ao contrário da herança de classes, uma classe pode implementar muitas interfaces, permitindo que desempenhe vários papéis ao mesmo tempo.
  • Polimorfismo. Objetos diferentes que compartilham uma interface podem ser usados de forma intercambiável onde essa interface é esperada.

Implementando uma Interface

Use a palavra-chave implements seguida do nome da interface e, em seguida, forneça um corpo para cada método que a interface declara.

<?php
interface Logger {
  public function log(string $message): void;
}

class ConsoleLogger implements Logger {
  public function log(string $message): void {
    echo "[LOG] {$message}\n";
  }
}

$logger = new ConsoleLogger();
$logger->log('App started');
// Output: [LOG] App started

ConsoleLogger honra o contrato Logger, então em qualquer lugar em que seu código espera um Logger, você pode passar um ConsoleLogger.

Type Hinting com uma Interface

O maior benefício vem quando você faz type-hint da interface em vez de uma classe concreta. A função abaixo funciona com qualquer Logger, então você pode mudar implementações sem reescrevê-la.

<?php
interface Logger {
  public function log(string $message): void;
}

class ConsoleLogger implements Logger {
  public function log(string $message): void {
    echo "[LOG] {$message}\n";
  }
}

class SilentLogger implements Logger {
  public function log(string $message): void {
    // intentionally does nothing
  }
}

function runJob(Logger $logger): void {
  $logger->log('Job finished');
}

runJob(new ConsoleLogger()); // Output: [LOG] Job finished
runJob(new SilentLogger());  // Output: (nothing)

Implementando Múltiplas Interfaces

Uma classe pode implementar várias interfaces ao mesmo tempo, separando seus nomes com vírgulas. É assim que o PHP contorna a falta de herança múltipla de classes.

<?php
interface Drawable {
  public function draw(): string;
}

interface Serializable {
  public function toArray(): array;
}

class Circle implements Drawable, Serializable {
  public function __construct(private float $radius) {}

  public function draw(): string {
    return "Circle(r={$this->radius})";
  }

  public function toArray(): array {
    return ['type' => 'circle', 'radius' => $this->radius];
  }
}

$c = new Circle(2.5);
echo $c->draw() . "\n";          // Output: Circle(r=2.5)
echo json_encode($c->toArray()); // Output: {"type":"circle","radius":2.5}

Constantes de Interface

Interfaces podem conter constantes, que toda classe implementadora herda. São úteis para valores fixos e compartilhados que pertencem ao contrato.

<?php
interface HttpStatus {
  const OK = 200;
  const NOT_FOUND = 404;
}

class Response implements HttpStatus {
  public function notFound(): int {
    return self::NOT_FOUND;
  }
}

$r = new Response();
echo $r->notFound();        // Output: 404
echo HttpStatus::OK;        // Output: 200

Estendendo Interfaces

Uma interface pode ser construída sobre outra com extends e, ao contrário das classes, uma interface pode estender múltiplas interfaces ao mesmo tempo. Uma classe que implementa a interface filha deve satisfazer todos os métodos herdados.

<?php
interface Readable {
  public function read(): string;
}

interface Writable {
  public function write(string $data): void;
}

interface ReadWrite extends Readable, Writable {}

class Memory implements ReadWrite {
  private string $buffer = '';

  public function read(): string {
    return $this->buffer;
  }

  public function write(string $data): void {
    $this->buffer .= $data;
  }
}

$m = new Memory();
$m->write('hello ');
$m->write('world');
echo $m->read(); // Output: hello world

Verificando uma Interface

Use o operador instanceof para confirmar que um objeto honra um dado contrato antes de chamar seus métodos.

<?php
interface Logger {
  public function log(string $message): void;
}

class ConsoleLogger implements Logger {
  public function log(string $message): void {
    echo $message . "\n";
  }
}

$obj = new ConsoleLogger();
var_dump($obj instanceof Logger); // Output: bool(true)

Interface vs. Classe Abstrata

Elas se sobrepõem, mas resolvem problemas diferentes:

InterfaceClasse abstrata
Corpos de métodosNão (apenas assinaturas)Sim (pode misturar concreto + abstrato)
PropriedadesNão (apenas constantes)Sim
Quantas por classeMuitas (implements A, B)Uma (extends A)
Use quandoClasses não relacionadas compartilham uma capacidadeClasses relacionadas compartilham código e estado

Prefira uma interface para descrever uma capacidade; prefira uma classe abstrata para compartilhar implementação parcial entre classes relacionadas. Se precisar compartilhar corpos de métodos entre classes não relacionadas, consulte PHP Traits.

Erros Comuns

  • Método faltando. Esquecer de implementar mesmo um único método da interface aciona um erro fatal na declaração da classe.
  • Reduzindo a visibilidade. Os métodos de interface são públicos; você não pode implementá-los como protected ou private.
  • Alterando a assinatura. Os parâmetros e o tipo de retorno do método implementado devem permanecer compatíveis com a interface, ou o PHP lança um erro.
  • Esperando propriedades. Interfaces declaram comportamento, não dados — elas não podem conter propriedades, apenas constantes.

Conclusão

As interfaces permitem que você programe para um contrato em vez de uma classe concreta: definem o que uma classe deve fazer, suportam múltiplas implementações e tornam o polimorfismo, os testes e a refatoração muito mais fáceis. Combine-as com herança e traits para projetar aplicações PHP flexíveis e de fácil manutenção.

Prática

Prática
Qual é o principal uso das interfaces PHP de acordo com a página do W3Docs?
Qual é o principal uso das interfaces PHP de acordo com a página do W3Docs?
Was this page helpful?