Lua
Object-Orientamento
Ricerca…
introduzione
Lua stessa non offre un sistema di classe. È tuttavia possibile implementare classi e oggetti come tabelle con pochi trucchi.
Sintassi
function <class>.new() return setmetatable({}, {__index=<class>}) end
Orientamento semplice degli oggetti
Ecco un esempio di base su come fare un sistema di classi molto semplice
Class = {}
local __instance = {__index=Class} -- Metatable for instances
function Class.new()
local instance = {}
setmetatable(instance, __instance)
return instance
-- equivalent to: return setmetatable({}, __instance)
end
Per aggiungere variabili e / o metodi, aggiungili alla classe. Entrambi possono essere sovrascritti per ogni istanza.
Class.x = 0
Class.y = 0
Class:getPosition()
return {self.x, self.y}
end
E per creare un'istanza della classe:
object = Class.new()
o
setmetatable(Class, {__call = Class.new}
-- Allow the class itself to be called like a function
object = Class()
E per usarlo:
object.x = 20
-- This adds the variable x to the object without changing the x of
-- the class or any other instance. Now that the object has an x, it
-- will override the x that is inherited from the class
print(object.x)
-- This prints 20 as one would expect.
print(object.y)
-- Object has no member y, therefore the metatable redirects to the
-- class table, which has y=0; therefore this prints 0
object:getPosition() -- returns {20, 0}
Modifica dei metametodi di un oggetto
avere
local Class = {}
Class.__meta = {__index=Class}
function Class.new() return setmetatable({}, Class.__meta)
Supponendo di voler cambiare il comportamento di un object = Class.new()
istanza singola object = Class.new()
utilizzando una metatable,
ci sono alcuni errori da evitare:
setmetatable(object, {__call = table.concat}) -- WRONG
Ciò scambia il vecchio metatable con quello nuovo, rompendo quindi l'ereditarietà della classe
getmetatable(object).__call = table.concat -- WRONG AGAIN
Tieni presente che i "valori" della tabella sono solo di riferimento; c'è, infatti, solo una tabella reale per tutte le istanze di un oggetto a meno che il costruttore non sia definito come in 1 , così facendo si modifica il comportamento di tutte le istanze della classe.
Un modo corretto per farlo:
Senza cambiare la classe:
setmetatable(
object,
setmetatable(
{__call=table.concat},
{__index=getmetatable(object)}
)
)
Come funziona? - Creiamo una nuova metatable come nell'errore numero 1, ma invece di lasciarla vuota, creiamo una copia soft per il metatable originale. Si potrebbe dire che la nuova metatabola "eredita" da quella originale come se fosse un'istanza di classe stessa. Ora possiamo sovrascrivere i valori del metatable originale senza modificarli.
Cambiando la classe:
1o (consigliato):
local __instance_meta = {__index = Class.__meta}
-- metatable for the metatable
-- As you can see, lua can get very meta very fast
function Class.new()
return setmetatable({}, setmetatable({}, __instance_meta))
end
2 ° (meno consigliato): vedi 1
1 function Class.new() return setmetatable({}, {__index=Class}) end