W3docs

implements

Scopri come la parola chiave "implements" di PHP applica i contratti delle interfacce. Sintassi, interfacce multiple, costanti e type hinting.

La parola chiave implements in PHP

La parola chiave implements indica a PHP che una classe si impegna a rispettare il contratto definito da un'interfaccia. Un'interfaccia elenca le firme dei metodi (e facoltativamente le costanti) ma nessun corpo di metodo; una classe che la implementa deve fornire un corpo concreto per ogni metodo dichiarato dall'interfaccia. In caso contrario, PHP lancia un errore fatale prima dell'esecuzione del programma.

Questa pagina tratta la sintassi, l'implementazione di più interfacce contemporaneamente, le costanti delle interfacce, il type hinting rispetto alle interfacce, gli errori comuni e le differenze tra implements ed extends. Se le interfacce sono nuove per te, inizia da Interfacce PHP e Cos'è l'OOP.

Sintassi

interface MyInterface {
  public function doSomething(); // signature only — no body
}

class MyClass implements MyInterface {
  public function doSomething() {
    // the concrete implementation lives here
  }
}

MyClass implements MyInterface è una promessa: "questa classe fornisce una versione funzionante di ogni metodo richiesto da MyInterface." L'interfaccia è il cosa; la classe è il come.

Un esempio di base

<?php

interface Animal {
  public function makeSound();
}

class Dog implements Animal {
  public function makeSound() {
    echo "Woof!";
  }
}

class Cat implements Animal {
  public function makeSound() {
    echo "Meow!";
  }
}

$animals = [new Dog(), new Cat()];
foreach ($animals as $animal) {
  $animal->makeSound(); // Output: Woof!Meow!
}

Poiché sia Dog che Cat implementano Animal, qualsiasi codice che si aspetta un Animal può lavorare con entrambi senza conoscere la classe concreta. Questo è il fondamento del polimorfismo in PHP.

Implementare più interfacce

A differenza di extends (una classe può estendere un solo genitore), una classe può implementare qualsiasi numero di interfacce — basta separarle con le virgole. La classe deve soddisfare ogni metodo di ogni interfaccia che elenca.

<?php

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

interface Notifier {
  public function notify(string $message): void;
}

class AlertService implements Logger, Notifier {
  public function log(string $message): void {
    echo "LOG: $message\n";
  }
  public function notify(string $message): void {
    echo "NOTIFY: $message\n";
  }
}

$service = new AlertService();
$service->log("Disk space low");    // Output: LOG: Disk space low
$service->notify("Disk space low"); // Output: NOTIFY: Disk space low

Questo è il modo in cui PHP ottiene i vantaggi dell'ereditarietà multipla (condivisione di più contratti) senza i suoi svantaggi (implementazioni ereditate ambigue).

Costanti delle interfacce e type hinting

Un'interfaccia può dichiarare costanti, e una classe che la implementa vi accede come fossero proprie. Il vero punto di forza, però, è il type hinting: quando si indica un parametro con il tipo dell'interfaccia, viene accettata qualsiasi classe che la implementa — così è possibile sostituire le implementazioni liberamente.

<?php

interface PaymentGateway {
  const CURRENCY = "USD";
  public function charge(float $amount): bool;
}

class StripeGateway implements PaymentGateway {
  public function charge(float $amount): bool {
    echo "Charging " . self::CURRENCY . " $amount\n";
    return true;
  }
}

// Accepts ANY PaymentGateway, not just StripeGateway
function processPayment(PaymentGateway $gateway, float $amount): void {
  $gateway->charge($amount);
}

processPayment(new StripeGateway(), 49.99); // Output: Charging USD 49.99

È anche possibile verificare un oggetto rispetto a un'interfaccia in fase di esecuzione con instanceof:

var_dump($gateway instanceof PaymentGateway); // bool(true)

Errori comuni e insidie

  • Omettere un metodo è fatale. Se una classe salta anche un solo metodo dell'interfaccia, PHP lancia Fatal error: Class X contains 1 abstract method and must therefore be declared abstract or implement the remaining methods. Il controllo avviene in fase di compilazione, prima dell'esecuzione di qualsiasi codice.
  • Le firme devono essere compatibili. La tua implementazione deve mantenere i tipi di parametro e di ritorno dichiarati dall'interfaccia (è possibile allargare i tipi di parametro e restringere i tipi di ritorno secondo le regole di varianza di PHP, ma le incompatibilità sono fatali).
  • I metodi delle interfacce sono implicitamente public. Non è possibile implementare un metodo di un'interfaccia come protected o private.
  • Le interfacce possono estendere altre interfacce. Usa interface B extends A per costruire su un'altra interfaccia; una classe che implementa B deve soddisfare i metodi di entrambe. Nota che si usa extends, non implements.

implements vs extends

Queste due parole chiave si confondono facilmente:

extendsimplements
Usato conuna classe genitore (o interfaccia→interfaccia)una o più interfacce
Eredita codice?sì — proprietà e corpi di metodino — solo il contratto (le firme)
Quanti?una classe estende una classeuna classe implementa molte interfacce

Una classe può fare entrambe le cose contemporaneamente: class Circle extends Shape implements JsonSerializable { ... }. Per i dettagli sull'ereditarietà, consulta PHP extends e, quando vuoi implementazioni parziali, classi astratte PHP.

Quando usare implements

Opta per un'interfaccia e implements quando:

  • Diverse classi non correlate devono essere intercambiabili (ad es. più gateway di pagamento, logger o driver di cache).
  • Vuoi eseguire il type hint su una capacità anziché su una classe concreta, mantenendo il codice liberamente accoppiato e facile da testare con i mock.
  • Stai definendo un contratto API pubblico che altre classi — incluse quelle scritte in seguito o da altri team — devono rispettare.

Se invece hai bisogno di condividere codice di implementazione effettivo tra classi correlate, usa l'ereditarietà di classe (extends) oppure una classe astratta.

Esercitati

Pratica
Qual è la funzione della parola chiave 'implements' in PHP?
Qual è la funzione della parola chiave 'implements' in PHP?
Was this page helpful?