Szukaj…


Wprowadzenie

Sama Lua nie oferuje systemu klasowego. Możliwe jest jednak zaimplementowanie klas i obiektów jako tabel za pomocą kilku sztuczek.

Składnia

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

Prosta orientacja obiektu

Oto podstawowy przykład wykonania bardzo prostego systemu klas

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

Aby dodać zmienne i / lub metody, po prostu dodaj je do klasy. Oba można zastąpić dla każdej instancji.

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

I aby utworzyć instancję klasy:

object = Class.new()

lub

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

I aby go użyć:

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}

Zmienianie meta metod obiektu

Mający

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

Zakładając, że chcemy zmienić zachowanie obiektu z pojedynczą instancją object = Class.new() za pomocą metatable,

jest kilka błędów, których należy unikać:

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

Wymienia to stare metatable na nowe, tym samym przerywając dziedziczenie klas

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

Należy pamiętać, że „wartości” z tabeli są jedynie odniesieniem; w rzeczywistości istnieje tylko jedna rzeczywista tabela dla wszystkich instancji obiektu, chyba że konstruktor jest zdefiniowany jak w 1 , więc w ten sposób modyfikujemy zachowanie wszystkich instancji klasy.


Jeden poprawny sposób to zrobić:

Bez zmiany klasy:

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

Jak to działa? - Tworzymy nowy metatabilny jak w pomyłce nr 1, ale zamiast pozostawiać go pustym, tworzymy miękką kopię do oryginalnego metatable. Można powiedzieć, że nowe metatowalne „dziedziczy” po oryginalnym, jakby to była sama instancja klasy. Możemy teraz zastąpić wartości oryginalnego metatable bez ich modyfikowania.

Zmiana klasy:

1. (zalecane):

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. (mniej zalecane): patrz 1


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



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow