Composizione vs ereditarietà
Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 56 di 91.
Nel capitolo precedente hai imparato che i trait forniscono una capacità «ha un» mentre l'ereditarietà stabilisce una relazione «è un». La composizione sviluppa ulteriormente il concetto «ha un», costruendo oggetti complessi a partire da oggetti più semplici e memorizzandoli come proprietà invece di ereditarli.
Con l'ereditarietà, una Car potrebbe estendere Vehicle. Con la composizione, una Car contiene un oggetto Engine:
<?php
class Engine {
public function start(): string {
return "Engine started";
}
}
class Car {
private Engine $engine;
public function __construct() {
$this->engine = new Engine();
}
public function start(): string {
return $this->engine->start();
}
}
$car = new Car();
echo $car->start();
Output:
Engine startedLa classe Car non eredita da Engine: ne possiede una. Questo approccio offre vantaggi significativi: puoi sostituire il motore con un’implementazione diversa, le classi rimangono debolmente accoppiate e puoi evitare le rigide gerarchie create da un’ereditarietà profonda.
Una linea guida comune nella programmazione orientata agli oggetti è "preferire la composizione all'ereditarietà." L'ereditarietà funziona bene per le gerarchie di tipi autentiche (un Dog è davvero un Animal), ma la composizione dà il meglio quando assembli funzionalità a partire da parti indipendenti. Puoi combinare più oggetti, sostituirli durante l'esecuzione e testare i componenti in modo isolato.
La prossima lezione approfondisce l'iniezione delle dipendenze, che si basa direttamente sulla composizione controllando il modo in cui gli oggetti ricevono le proprie dipendenze.
Sfida
FacileCostruiamo un sistema informatico usando la composizione, in cui un Computer è assemblato a partire da oggetti componente separati invece di ereditare da essi. Questo dimostra come la composizione consenta di creare oggetti complessi a partire da parti più semplici e indipendenti.
Organizzerai il codice in tre file:
Processor.php: crea una classeProcessorche rappresenta una CPU. Usa la promozione dei parametri del costruttore per definire un$modelprivato (stringa) e un$coresprivato (intero). Aggiungi un metodogetSpecs()che restituisce"[model] ([cores] cores)".Memory.php: crea una classeMemoryche rappresenta la RAM. Usa la promozione dei parametri del costruttore per definire un$sizeprivato (intero che rappresenta i GB). Aggiungi un metodogetCapacity()che restituisce"[size]GB RAM".main.php: includi entrambi i file dei componenti e crea una classeComputerche usa la composizione.Computerdovrà:- Memorizzare un oggetto
Processore un oggettoMemorycome proprietà private - Accettare nel costruttore un modello di processore, il numero di core e la dimensione della memoria
- Creare internamente gli oggetti componente durante la costruzione
- Avere un metodo
describe()che restituisce"Computer with [processor specs] and [memory capacity]"
Riceverai tre input: un modello di processore, un numero di core e una dimensione della memoria in GB. Crea un
Computercon queste specifiche e stampa il risultato della chiamata adescribe().- Memorizzare un oggetto
Nota che Computer non estende Processor o Memory. Li contiene. Questa relazione «ha un» tramite la composizione mantiene ogni componente indipendente e riutilizzabile, consentendo al contempo a Computer di delegare alle sue parti quando necessario.
Provalo tu
<?php
require_once 'Processor.php';
require_once 'Memory.php';
class Computer
{
// TODO: Definire proprietà private per memorizzare gli oggetti Processor e Memory
// TODO: Il costruttore deve accettare il modello del processore, il numero di core e la dimensione della memoria
// e creare internamente gli oggetti dei componenti
public function __construct()
{
// TODO: Creare gli oggetti Processor e Memory e memorizzarli
}
// TODO: Implementare il metodo describe() che restituisce
// "Computer with [processor specs] and [memory capacity]"
public function describe(): string
{
// TODO: Delegare agli oggetti dei componenti e restituire una stringa formattata
}
}
// Leggere l'input
$processorModel = trim(fgets(STDIN));
$cores = intval(fgets(STDIN));
$memorySize = intval(fgets(STDIN));
// TODO: Creare un Computer con le specifiche fornite e stampare il risultato di describe()
?>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