Chiamare i metodi della classe genitore
Fa parte della sezione Programmazione orientata agli oggetti del percorso Lua di Coddy. Lezione 38 di 70.
A volte sovrascrivere completamente un metodo non è ciò che vuoi. Potresti invece voler estendere il comportamento della classe genitore: fare ciò che fa la classe genitore e poi aggiungere qualcosa in più. Per riuscirci, puoi chiamare direttamente il metodo della classe genitore all'interno del metodo sovrascritto della classe figlia.
La tecnica usa la sintassi con il punto con il nome della classe padre, passando esplicitamente self come primo argomento:
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- Dog estende il comportamento della classe padre
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
Animal.speak(self) -- Chiama prima il metodo della classe padre
print(self.name .. " wags tail happily")
endLa riga chiave è Animal.speak(self). Usando la sintassi del punto sulla classe genitore e passando manualmente self, invochiamo il metodo originale prima di aggiungere il nostro comportamento:
local buddy = Dog:new("Buddy")
buddy:speak()
-- Output:
-- Buddy emette un suono
-- Buddy scodinzola feliceQuesto schema è utile quando il metodo della classe genitore svolge un lavoro importante che non vuoi duplicare. La classe figlia può eseguire la logica della classe genitore prima, dopo o persino nel mezzo del proprio codice, dandoti il pieno controllo su come combinare i comportamenti.
Sfida
FacileCostruiamo un sistema di saluti in cui una FormalPerson estende il comportamento di una normale Person! Invece di sostituire completamente il modo in cui una persona si presenta, la versione formale eseguirà prima la presentazione standard, poi aggiungerà un tocco di cortesia.
Organizzerai il codice in tre file:
Person.lua: la tua classe base con un costruttore:new(name)che memorizza il nome della persona. Includi un metodo:introduce()che stampa il nome della persona seguito dasays hi. Questo è il comportamento di base che verrà esteso.FormalPerson.lua: una classe figlia che eredita da Person. Il suo costruttore dovrebbe chiamare il costruttore della classe genitore per gestire il nome. Sovrascrivi il metodo:introduce(), ma invece di sostituire interamente il comportamento della classe genitore, chiama prima il metodo della classe genitore usandoPerson.introduce(self), poi stampa una riga aggiuntiva con il nome della persona seguito dabows politely.main.lua: importa il modulo FormalPerson, legge un nome dall'input, crea un'istanza di FormalPerson e chiama:introduce()per vedere combinati entrambi i comportamenti.
Riceverai un input: il nome della persona.
Quando chiami :introduce() su una FormalPerson, dovrebbe produrre due righe di output: la prima dal metodo della classe genitore, la seconda aggiunta dalla classe figlia:
{name} says hi
{name} bows politelyPer esempio, se l'input è Eleanor, l'output dovrebbe essere:
Eleanor says hi
Eleanor bows politelyL'intuizione fondamentale è che FormalPerson non duplica la logica di "says hi". Delega quel compito al metodo della classe genitore, poi aggiunge il proprio comportamento distintivo. In questo modo il codice rimane pulito e mostri come le classi figlie possano estendere, anziché sostituire, le funzionalità della classe genitore!
Provalo tu
-- main.lua: Punto di ingresso per il sistema di saluto
local FormalPerson = require('FormalPerson')
-- Leggi il nome della persona dall'input
local name = io.read()
-- TODO: Crea un'istanza di FormalPerson con il nome fornito
-- TODO: Chiama il metodo introduce sull'istanza di FormalPerson
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 deposito7Polimorfismo e sovrascrittura
Sovrascrivere i metodiChiamare i metodi della classe genitoreDuck TypingInterfaccia comuneVerificare il tipoRiepilogo - Ruoli dei dipendenti2Schema 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 formeEsercitati da solo: Compilatore Lua online