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:
- Ereditare i membri dal genitore senza modifiche.
- Aggiungere nuove proprietà e metodi propri.
- 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)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
publicvengono ereditati e sono utilizzabili ovunque. - I membri
protectedvengono ereditati e sono accessibili all'interno della classe figlia, ma non dall'esterno. - I membri
privatenon 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 100Consulta 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à
privatenel genitore è invisibile alla classe figlia; rendilaprotectedse 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
- Ereditarietà PHP — il concetto più ampio che
extendsimplementa. - Classi e oggetti PHP — i blocchi fondamentali.
- Classi astratte — genitori che devono essere estesi.
- Interfacce — contratti per classi non correlate.