Zoeken…


Invoering

Lua zelf biedt geen klassensysteem. Het is echter mogelijk om klassen en objecten als tabellen te implementeren met slechts een paar trucs.

Syntaxis

  • function <class>.new() return setmetatable({}, {__index=<class>}) end

Eenvoudige objectoriëntatie

Hier is een eenvoudig voorbeeld van hoe u een zeer eenvoudig klassensysteem kunt uitvoeren

Class = {}
local __instance = {__index=Class} -- Metatable for instances
function Class.new()
    local instance = {}
    setmetatable(instance, __instance)
    return instance
-- equivalent to: return setmetatable({}, __instance)
end

Om variabelen en / of methoden toe te voegen, voegt u ze gewoon toe aan de klasse. Beide kunnen voor elke instantie worden opgeheven.

Class.x = 0
Class.y = 0
Class:getPosition()
    return {self.x, self.y}
end

En om een instantie van de klasse te maken:

object = Class.new()

of

setmetatable(Class, {__call = Class.new}
    -- Allow the class itself to be called like a function
object = Class()

En om het te gebruiken:

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}

Metamethoden van een object veranderen

Het hebben van

local Class = {}
Class.__meta = {__index=Class}
function Class.new() return setmetatable({}, Class.__meta)

Ervan uitgaande dat we het gedrag van een object = Class.new() één exemplaar object = Class.new() met een metatable,

er zijn een paar fouten te vermijden:

setmetatable(object, {__call = table.concat}) -- WRONG

Hiermee wordt de oude metatabel vervangen door de nieuwe, waardoor de klasse-overerving wordt verbroken

getmetatable(object).__call = table.concat -- WRONG AGAIN

Houd er rekening mee dat de tabel "waarden" slechts een referentie zijn; er is in feite slechts één tabel voor alle instanties van een object, tenzij de constructor is gedefinieerd als in 1 , dus door dit te doen wijzigen we het gedrag van alle instanties van de klasse.


Een juiste manier om dit te doen:

Zonder de klasse te veranderen:

setmetatable(
    object,
    setmetatable(
        {__call=table.concat},
        {__index=getmetatable(object)}
    )
)

Hoe werkt dit? - We maken een nieuwe metatabel zoals in fout # 1, maar in plaats van deze leeg te laten, maken we een zachte kopie naar de originele metatabel. Je zou kunnen zeggen dat de nieuwe metatable van de originele 'erft' alsof het een klasse-instantie zelf is. We kunnen nu de waarden van de oorspronkelijke metatabel overschrijven zonder ze te wijzigen.

De klasse wijzigen:

1e (aanbevolen):

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

2e (minder aanbevolen): zie 1


1 function Class.new() return setmetatable({}, {__index=Class}) end



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow