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



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow