Tratti vs ereditarietà
Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 55 di 91.
Ora che hai capito come funzionano i trait, chiariamo quando usare i trait invece dell'ereditarietà. Entrambi consentono di riutilizzare il codice, ma hanno scopi diversi e caratteristiche distinte.
L'ereditarietà stabilisce una relazione «è-un». Una classe Dog che estende Animal significa che un cane è un animale. La classe figlia eredita l'identità della classe genitore e può essere utilizzata ovunque sia previsto il tipo genitore.
I trait forniscono una funzionalità «has-a». Quando una classe usa un trait Loggable, ha funzionalità di logging, ma non diventa un logger. I trait aggiungono comportamento senza cambiare ciò che la classe è fondamentalmente.
<?php
// Ereditarietà: Dog È un Animal
class Animal {
public function breathe(): void {
echo "Breathing";
}
}
class Dog extends Animal {
public function bark(): void {
echo "Woof!";
}
}
// Trait: Dog HA la capacità di registrare i log
trait Loggable {
public function log(string $msg): void {
echo "Log: $msg";
}
}
class Cat extends Animal {
use Loggable;
}
Differenze principali da ricordare:
| Aspetto | Ereditarietà | Trait |
|---|---|---|
| Relazione | è-un | ha-una-funzionalità |
| Limite | Un solo genitore | Sono consentiti più trait |
| Controllo del tipo | Funziona con instanceof | Nessuna identità di tipo |
| Ideale per | Relazioni gerarchiche | Comportamenti condivisi tra classi non correlate |
Usa l’ereditarietà quando le classi condividono un’identità comune. Usa i trait quando classi non correlate hanno bisogno delle stesse funzionalità senza appartenere allo stesso albero genealogico.
Sfida
FacileCostruiamo un sistema di veicoli che mostri quando usare l'ereditarietà anziché i trait. Creerai una gerarchia di veicoli che condividono un'identità comune tramite l'ereditarietà, aggiungendo al contempo funzionalità trasversali tramite i trait.
Organizzerai il codice in quattro file:
Trackable.php: crea un trait chiamatoTrackableche fornisca la funzionalità di tracciamento GPS. Il trait dovrebbe avere:- Una proprietà privata
$location(stringa) - Un metodo
setLocation(string $location)che memorizzi la posizione corrente - Un metodo
getLocation()che restituisca"Location: [location]"
- Una proprietà privata
Vehicle.php: crea una classe baseVehicleche stabilisca la relazione «è un». Includi il file del trait. Usa la promozione del costruttore per definire una proprietà$brandprotetta. Aggiungi un metododescribe()che restituisca"Vehicle: [brand]". Questa classe dovrebbe usare il traitTrackable, poiché tutti i veicoli della nostra flotta avranno il GPS.Car.php: crea una classeCarche estendaVehicle. Includi il file Vehicle. Usa la promozione del costruttore per accettare la marca e una proprietà privata$doors(intero). Chiama il costruttore del genitore passando la marca. Sovrascrivi il metododescribe()in modo che restituisca"Car: [brand] with [doors] doors".main.php: includi il file Car. Riceverai tre input: il nome di una marca, il numero di porte e una stringa con la posizione. Crea un'istanza diCar, imposta la sua posizione, quindi stampa due righe:- Il risultato della chiamata a
describe() - Il risultato della chiamata a
getLocation()
- Il risultato della chiamata a
Nota come funzionano insieme l'ereditarietà e i trait: Car è un Vehicle (l'ereditarietà stabilisce l'identità), mentre Vehicle ha la funzionalità di tracciamento (il trait aggiunge comportamento). Potresti usare instanceof Vehicle per verificare se qualcosa è un veicolo, ma non esiste un tipo «Trackable» da usare per il controllo: questa è la differenza fondamentale tra i due approcci.
Provalo tu
<?php
// File principale - crea e verifica l'istanza di Car
// TODO: Includi il file Car.php
// Leggi i dati di input
$brand = trim(fgets(STDIN));
$doors = intval(trim(fgets(STDIN)));
$location = trim(fgets(STDIN));
// TODO: Crea un'istanza di Car con brand e doors
// TODO: Imposta la posizione dell'auto
// TODO: Stampa il risultato di describe()
// TODO: Stampa il risultato di getLocation()
?>Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave $thisMetodiProprietàCostruttore (__construct)Distruttore (__destruct)Riepilogo - Calcolatrice semplice4Ereditarietà
Ereditarietà di baseLa parola chiave parent::Sovrascrittura dei metodiLa parola chiave finalClassi astratteRiepilogo - Gerarchia dei dipendenti7Incapsulamento
Pubblico, Protetto, PrivatoApprofondimento sui modificatori di accessoGetter e SetterOccultamento delle informazioniPromozione dei parametri del costruttore (8.0)Riepilogo - Sistema di gestione dei registri degli studenti10Concetti avanzati di programmazione a oggetti
Composizione vs ereditarietàDependency InjectionClassi anonimeEnumerazioni (PHP 8.1)Fibers (PHP 8.1)Approfondimento sulla clonazione degli oggettiGeneratori e iteratori13Modelli di progettazione, parte 2
Modello CommandModello AdapterModello DecoratorModello Template MethodModello StateModello CompositeModello Repository2Namespace e autoloading
Introduzione ai namespaceLa keyword useStandard di autoloading PSR-4Autoloader di ComposerRiepilogo - Progetto organizzato5Interfacce e contratti
Introduzione alle interfacceImplementare le interfacceImplementare più interfacceInterfaccia vs classe astrattaType hinting con le interfacceRiepilogo - Calcolatore di forme8Metodi magici
Introduzione ai metodi magici__toString e __debugInfo__get, __set, __isset, __unset__call e __callStatic__clone e clonazione degli oggetti__serialize e __unserializeRiepilogo - Collezione personalizzata11Sistema dei tipi e gestione degli errori
Dichiarazioni di tipoTipi nullableTipi unione e intersezioneClassi di eccezioneGerarchia di eccezioni personalizzataTry, Catch, FinallyRiepilogo - Validatore di moduli14Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente3Proprietà delle classi
Proprietà di istanza e staticheCostanti nelle classiMetodi e proprietà staticiProprietà private e protectedProprietà readonly (PHP 8.1)Riepilogo - Gestore di conti bancari6Polimorfismo
Ridefinizione dei metodi, ripresaPolimorfismo tramite interfacceSuggerimenti sui tipi e tipi UnionBinding statico tardivoRiepilogo - Processore di pagamenti9Tratti
Introduzione ai trattiUtilizzare più trattiRisoluzione dei conflitti tra trattiMetodi astratti nei trattiTratti vs ereditarietà12Design pattern - Parte 1
Introduzione ai design patternPattern SingletonPattern FactoryPattern ObserverPattern StrategyEsercitati da solo: Compilatore PHP online