Relazione Has-A
Fa parte della sezione Programmazione orientata agli oggetti del percorso Lua di Coddy. Lezione 49 di 70.
Durante tutto il corso, hai usato l’ereditarietà per condividere il comportamento tra classi: un Dog “è un” Animal. Ma l’ereditarietà non è sempre lo strumento giusto.
A volte, gli oggetti non condividono un albero genealogico; invece, un oggetto semplicemente contiene un altro. Questo si chiama composizione e modella una relazione «ha-un».
Considera un'auto. Un'auto non è un tipo di motore. Ha un motore. Il motore è un oggetto separato che si trova all'interno dell'auto:
local Engine = {}
Engine.__index = Engine
function Engine:new(horsepower)
local obj = {horsepower = horsepower}
setmetatable(obj, Engine)
return obj
end
local Car = {}
Car.__index = Car
function Car:new(model, engine)
local obj = {
model = model,
engine = engine -- Memorizza l'oggetto Engine all'interno di Car
}
setmetatable(obj, Car)
return obj
endQuando crei un'auto, passi un oggetto motore esistente al suo costruttore:
local myEngine = Engine:new(200)
local myCar = Car:new("Sedan", myEngine)
print(myCar.engine.horsepower) -- 200L’auto non eredita dal motore. Ne mantiene semplicemente un riferimento. Questo mantiene indipendenti entrambe le classi. Potresti sostituirlo con un motore diverso o usare la stessa classe Motore in una motocicletta.
La composizione ti dà una flessibilità che l’ereditarietà non può offrire: assembli oggetti a partire da componenti invece di vincolarli a una rigida gerarchia di famiglie.
Sfida
FacileCostruiamo un sistema informatico usando la composizione! Invece dell'ereditarietà, creerai un Computer che ha una CPU al suo interno: dimostrando la relazione "has-a".
Organizzerai il codice in tre file:
CPU.lua: Crea una classe CPU con un costruttore:new(brand, speed)che memorizza il nome del produttore e la velocità in GHz. Includi un metodo:getInfo()che restituisce una stringa nel formato:{brand} @ {speed}GHzComputer.lua: Crea una classe Computer il cui costruttore:new(model, cpu)accetta il nome di un modello e un oggetto CPU. Computer memorizza al suo interno l'oggetto CPU (composizione!). Includi un metodo:describe()che stampa il modello del computer e le informazioni della sua CPU.main.lua: Mettiamo tutto insieme! Leggi gli input per il produttore della CPU, la velocità della CPU e il modello del computer. Crea prima un oggetto CPU, poi passalo al costruttore di Computer. Infine, chiama il metodo:describe()del computer.
Riceverai tre input:
- Il produttore della CPU (una stringa)
- La velocità della CPU in GHz (un numero)
- Il nome del modello del computer (una stringa)
L'output dovrebbe mostrare la descrizione del computer, che include le informazioni della CPU contenuta al suo interno:
Model: {model}
CPU: {brand} @ {speed}GHzPer esempio, se gli input sono Intel, 3.5 e WorkStation, l'output dovrebbe essere:
Model: WorkStation
CPU: Intel @ 3.5GHzNota che Computer non eredita da CPU. Semplicemente conserva un riferimento a una CPU. Il metodo :describe() di Computer accede ai dati della CPU tramite l'oggetto memorizzato, mostrando come la composizione consenta di costruire oggetti complessi a partire da parti più semplici!
Provalo tu
-- main.lua
-- Metti insieme tutti gli elementi usando la composizione
local CPU = require('CPU')
local Computer = require('Computer')
-- Leggi gli input
local cpuBrand = io.read()
local cpuSpeed = tonumber(io.read())
local computerModel = io.read()
-- TODO: Crea un oggetto CPU con la marca e la velocità
-- TODO: Crea un oggetto Computer con il modello e l'oggetto CPU
-- TODO: Chiama il metodo describe() del computer per stampare l'output
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
1Il concetto di «self»
Tabelle con funzioni«self» esplicitoLa sintassi dei due puntiPunto o due puntiRiepilogo - Spostare il punto4Progetto: Banca digitale
Configurazione del progettoMetodo di deposito2Schema del prototipo di classe
Il concetto di prototipoCollegare con __indexIl costruttore :new()Inizializzare gli attributiIstanze indipendentiRiepilogo - Fabbrica di auto5Sovraccarico degli operatori nella OOP
Sommare oggettiSottrarre oggettiConcatenare oggettiConfrontare oggetti (<, >)Ripasso - Calcoli con il portafoglio8Incapsulamento
Convenzioni di denominazioneClosure per la privacyAccesso tramite closureTabelle di sola letturaLogica di convalidaRiepilogo - Cassaforte sicura11Modelli di progettazione (base)
Funzioni factoryTabella singletonPattern IteratorObserver (listener)Riepilogo - Factory per logger3Stato e comportamento degli oggetti
Variabili di istanzaMetodi getterMetodi setterProprietà calcolateFormattazione delle stringheControlli di uguaglianzaRiepilogo - Voto dello studente6Fondamenti dell'ereditarietà
Configurare l'ereditarietàEreditare i metodiEstendere il costruttoreAggiungere metodi alla classe figliaCondiviso vs specificoRiepilogo - Gerarchia delle forme9Composizione e mixin
Relazione Has-ADelegaMixin sempliciApplicare più mixinMixin vs ereditarietàRiepilogo - Assemblaggio di robotEsercitati da solo: Compilatore Lua online