W3docs

extends

La parola chiave "extends" in PHP permette a una classe figlia di ereditare proprietà e metodi da una classe genitore nella programmazione orientata agli oggetti.

La parola chiave PHP extends

extends è il modo in cui una classe dichiara l'ereditarietà in PHP: una classe figlia (o sottoclasse) costruita con extends acquisisce automaticamente le proprietà e i metodi non privati della sua classe genitore (o superclasse). Invece di copiare il codice condiviso in ogni classe correlata, lo si scrive una volta nel genitore e si lascia che le sottoclassi lo specializzino.

Questa pagina tratta la sintassi, come chiamare il codice del genitore con parent::, come funziona l'override dei metodi, le regole dei modificatori di accesso che determinano cosa eredita una classe figlia e gli errori comuni. PHP supporta solo l'ereditarietà singola — una classe può usare extends con esattamente un genitore (usa le interfacce quando hai bisogno che un tipo svolga più ruoli).

Sintassi

class ChildClass extends ParentClass {
  // additional or overriding members
}

La classe figlia può fare tre cose:

  1. Ereditare i membri dal genitore senza modifiche.
  2. Aggiungere nuove proprietà e metodi propri.
  3. Sovrascrivere un metodo ereditato ridichiarandolo con lo stesso nome.

Un primo esempio

<?php

class Fruit {
  public $name;
  public $color;

  public function __construct($name, $color) {
    $this->name = $name;
    $this->color = $color;
  }

  public function getInfo() {
    echo "This fruit is a {$this->name} and it is {$this->color}.";
  }
}

// Apple inherits everything from Fruit and overrides getInfo().
class Apple extends Fruit {
  public function getInfo() {
    echo "This fruit is an {$this->name} and it is {$this->color}.";
  }
}

$apple = new Apple("apple", "red");
$apple->getInfo();
// Output: This fruit is an apple and it is red.

Apple non dichiara mai $name, $color né un costruttore — li eredita da Fruit. Ridefinisce soltanto getInfo(), che sovrascrive la versione del genitore.

Chiamare il genitore con parent::

Una classe figlia spesso vuole estendere il comportamento del genitore anziché sostituirlo. Quando una classe figlia definisce il proprio costruttore, PHP non chiama automaticamente il costruttore del genitore — devi farlo esplicitamente con parent::__construct(). La stessa sintassi parent:: funziona per qualsiasi metodo sovrascritto.

<?php

class Car {
  public $model;
  public $year;

  public function __construct($model, $year) {
    $this->model = $model;
    $this->year = $year;
  }

  public function getInfo() {
    echo "This car is a {$this->model} from {$this->year}.";
  }
}

class Toyota extends Car {
  public function __construct($year) {
    // Fill in the model, defer the rest to the parent.
    parent::__construct("Toyota", $year);
  }

  public function getInfo() {
    parent::getInfo();            // reuse the parent's output...
    echo " (built by Toyota)";    // ...then add to it.
  }
}

$toyota = new Toyota(2021);
$toyota->getInfo();
// Output: This car is a Toyota from 2021. (built by Toyota)
Result

Se Toyota non avesse nessun costruttore, erediterebbe quello di Car e lo si creerebbe con new Toyota("Corolla", 2021).

Cosa può — e cosa non può — ereditare una classe figlia

I modificatori di accesso determinano la visibilità attraverso il confine dell'ereditarietà:

  • I membri public vengono ereditati e sono utilizzabili ovunque.
  • I membri protected vengono ereditati e sono accessibili all'interno della classe figlia, ma non dall'esterno.
  • I membri private non sono accessibili nella classe figlia. Esistono ancora sull'object, ma la classe figlia non può vederli per nome.
<?php

class Account {
  public $owner = "Ann";
  protected $balance = 100;   // visible to children
  private $pin = "1234";      // hidden from children

  public function reveal() {
    return "$this->owner, balance $this->balance, pin $this->pin";
  }
}

class SavingsAccount extends Account {
  public function summary() {
    // $this->balance works (protected); $this->pin would be null/undefined.
    return "{$this->owner} has {$this->balance}";
  }
}

$s = new SavingsAccount();
echo $s->summary();
// Output: Ann has 100
Result

Consulta i modificatori di accesso PHP per le regole complete su public / protected / private.

Bloccare una classe o un metodo con final

Usa la parola chiave final per impedire ulteriori estensioni. Una final class non può essere un genitore; un metodo final non può essere sovrascritto da una sottoclasse. Ciò è utile quando la sovrascrittura romperebbe un invariante su cui la tua classe fa affidamento.

class PaymentGateway {
  final public function charge() { /* must not be altered */ }
}

Errori comuni

  • Dimenticare parent::__construct(). Definire un costruttore nella classe figlia oscura quello del genitore. Se dimentichi di chiamarlo, le proprietà del genitore rimangono non inizializzate.
  • Ereditarietà singola. class A extends B, C è un errore di sintassi. Componi il comportamento con le interfacce o i trait.
  • I membri privati non vengono condivisi. Una proprietà private nel genitore è invisibile alla classe figlia; rendila protected se le sottoclassi ne hanno bisogno.
  • Le firme degli override devono rimanere compatibili. Un metodo di sovrascrittura deve accettare gli stessi argomenti (o più ampi), altrimenti PHP genera un avviso.

Argomenti correlati

Esercizio

Pratica
Qual è il significato della parola chiave 'extends' in PHP?
Qual è il significato della parola chiave 'extends' in PHP?
Was this page helpful?