Variabili di istanza
Fa parte della sezione Programmazione orientata agli oggetti del percorso Lua di Coddy. Lezione 12 di 70.
Benvenuto in un nuovo capitolo dedicato a come gli oggetti gestiscono i propri dati interni. Hai imparato a creare classi e istanze: ora è il momento di scoprire come ogni istanza memorizza e gestisce il proprio stato unico.
Le variabili di istanza sono campi che appartengono esclusivamente a un singolo oggetto. Quando assegni un valore a self.something all'interno di un metodo o di un costruttore, quei dati esistono solo in quella specifica istanza. Gli altri oggetti della stessa classe hanno le proprie copie separate.
Questo diventa particolarmente importante quando si memorizzano dati complessi come le tabelle. Considera un sistema di inventario in cui ogni personaggio trasporta oggetti diversi:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- Ogni istanza riceve una propria tabella vuota
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
endLa riga chiave è instance.items = {}. Creando una nuova tabella vuota all'interno del costruttore, ogni oggetto inventario riceve il proprio elenco distinto. Se invece definissi items nella tabella della classe stessa, tutte le istanze condividerebbero accidentalmente la stessa tabella: aggiungere una spada a un personaggio la darebbe a tutti!
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- Output: 1
print(#bag2.items) -- Output: 1Ogni inventario mantiene la propria raccolta. Questo schema si applica ogni volta che un'istanza deve tenere traccia di dati che cambiano in modo indipendente: elenchi, contatori o qualsiasi stato mutabile specifico di quell'oggetto.
Sfida
FacileCostruiamo un sistema ShoppingCart in cui ogni carrello mantiene un elenco di prodotti separato dagli altri. Questo dimostrerà come le variabili di istanza mantengano i dati isolati tra gli oggetti: aggiungere articoli a un carrello non influirà sugli altri!
Organizzerai il codice in due file:
ShoppingCart.lua: definisci la classeShoppingCart, in cui ogni istanza ha la propria tabellaproducts. Includi:- Un costruttore
:new()che inizializza un elenco di prodotti vuoto per ogni carrello - Un metodo
:addProduct(productName)che aggiunge un prodotto all'elenco di questo carrello - Un metodo
:listProducts()che stampa ogni prodotto su una riga separata
- Un costruttore
main.lua: richiedi il modulo ShoppingCart e crea due carrelli separati. Aggiungi prodotti diversi a ciascun carrello per dimostrare che mantengono inventari indipendenti.
Riceverai quattro input:
- Primo prodotto da aggiungere al carrello A
- Secondo prodotto da aggiungere al carrello A
- Primo prodotto da aggiungere al carrello B
- Secondo prodotto da aggiungere al carrello B
Nel file principale:
- Crea due carrelli della spesa:
cartAecartB - Aggiungi i primi due prodotti a
cartA - Aggiungi gli ultimi due prodotti a
cartB - Stampa
Cart A:, poi elenca i prodotti del carrello A - Stampa
Cart B:, poi elenca i prodotti del carrello B
Per esempio, se gli input sono Apple, Bread, Milk e Eggs, l'output dovrebbe essere:
Cart A:
Apple
Bread
Cart B:
Milk
EggsRicorda: la chiave è inizializzare products come una nuova tabella vuota all'interno del costruttore. In questo modo ogni istanza del carrello ottiene il proprio elenco separato, invece di condividere un'unica tabella tra tutti i carrelli.
Provalo tu
-- Carica il modulo ShoppingCart
local ShoppingCart = require('ShoppingCart')
-- Leggi gli input
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()
-- TODO: Crea due carrelli della spesa: cartA e cartB
-- TODO: Aggiungi product1 e product2 a cartA
-- TODO: Aggiungi product3 e product4 a cartB
-- TODO: Stampa "Cart A:", poi elenca i prodotti di cartA
-- TODO: Stampa "Cart B:", poi elenca i prodotti di cartB
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 formeEsercitati da solo: Compilatore Lua online