Sök…


Introduktion

Lua erbjuder själv inget klasssystem. Det är dock möjligt att implementera klasser och objekt som tabeller med bara några trick.

Syntax

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

Enkel objektorientering

Här är ett grundläggande exempel på hur man gör ett mycket enkelt klasssystem

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

För att lägga till variabler och / eller metoder, lägg bara till dem i klassen. Båda kan åsidosättas för varje instans.

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

Och för att skapa en instans av klassen:

object = Class.new()

eller

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

Och för att använda det:

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}

Ändra metametoder för ett objekt

Har

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

Förutsatt att vi vill ändra beteendet hos ett enda object = Class.new() med en metatabel,

det finns några misstag att undvika:

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

Detta utbyter den gamla metatabeln med den nya och bryter därför klassarvet

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

Kom ihåg att tabellvärden endast är referens; det finns faktiskt bara en faktisk tabell för alla instanser av ett objekt såvida inte konstruktören definieras som i 1 , så genom att göra detta ändrar vi beteendet hos alla instanser i klassen.


Ett korrekt sätt att göra detta:

Utan att ändra klassen:

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

Hur fungerar detta? - Vi skapar en ny metatabel som i misstag nr 1, men istället för att lämna den tom, skapar vi en mjuk kopia till den ursprungliga metatabeln. Man kan säga att den nya metatable "ärver" från den ursprungliga som om det var en klassinstans själv. Vi kan nu åsidosätta värdena på den ursprungliga metatabeln utan att ändra dem.

Ändra klass:

1: a (rekommenderas):

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: a (mindre rekommenderas): se 1


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



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow