2012-03-08 8 views
5

Próbuję zrozumieć, co robi ta funkcja. Czy ktoś może mi to wyjaśnić?Próba zrozumienia tego lua snippet

function newInstance (class) 
    local o = {} 
    setmetatable (o, class) 
    class.__index = class 
    return o 
end 

To się nazywa tak:

self = newInstance (self) 
+0

Proszę ktoś dać lepszy tytuł na to pytanie bo ja myślę, że to pomoże niektórych deweloperów tam. – chchrist

Odpowiedz

6

Funkcja ta najwyraźniej służy do zapewnienia wariant OOP w Lua (trochę zaniedbany moim zdaniem).

To jest fabryka dla klasy.

może być przepisana następująco, dla jasności:

C = { } 

C.foo = function(self) -- just some method, so class would not be empty 
    print("foo method called", tostring(self)) 
end 

C.__index = C -- (A) 

function newInstance(class) 
    return setmetatable({ }, class) -- (B) 
end 

Teraz jeśli tworzymy dwie nowe instancje C, widzimy wyraźnie, że obie mają foo() metoda, ale różni się samo:

o1 = newInstance(C) 
o1:foo() --> foo method called table: 0x7fb3ea408ce0 

o2 = newInstance(C) 
o2:foo() --> foo method called table: 0x7fb3ea4072f0 

metody foo są takie same:

print(o1.foo, o2.foo, o1.foo == o2.foo and "equal" or "different") 
--> function: 0x7fb3ea410760 function: 0x7fb3ea410760 equal 

to dlatego tabela C ("klasy") jest __index ((A) powyżej) z metatable o1 i o2, zestaw w (B). Ale o1 i o2 są w rzeczywistości dwiema różnymi tabelami utworzonymi pod numerem (B) ("wystąpienia klas" lub "obiekty").

Uwaga: ustawiliśmy C.__index na równe C na (A), abyśmy mogli ponownie wykorzystać jedną tabelę. Następujący ma taki sam efekt:

prototype = { } 

prototype.foo = function(self) -- just some method, so class would not be empty 
    print("foo method called", tostring(self)) 
end 

C = { __index = prototype } 

function newInstance(class) 
    return setmetatable({ }, class) 
end 

o = newInstance(C) 
1

Służy do osiągnięcia obiektowego zachowania w Lua. Lua używa opartego na prototypach dziedziczenia (podobnego do Javascript) zamiast dziedziczenia opartego na klasach (jak Java lub C++). Chodzi o to, że wszystkie metody klasy są implementowane jako część obiektu prototypowego i dziedziczą obiekty delegowane do prototypu podczas rozmowy.

Załóżmy na przykład, chcesz klasa myClass dostarczenie sposobu getMagicNumber:

local myClass = { 
    getMagicNumber = function(self) 
     return self.theNumber; 
    end }; 

local obj = newInstance(myClass); 
obj.theNumber = 42; 
print(obj:getMagicNumber()); -- supposed to return 42 

To trochę trywialny przykład, ale mam nadzieję, że masz pomysł. Co się dzieje, to: newInstance tworzy nową tabelę z jej metatable wskazującą na myClass i również zapewnia, że ​​pole __index punktów metatable do myClass również. Jak opisuje podręcznik Lua na __index, po próbie wywołania getMagicNumber na tej nowej tabeli, następuje: Najpierw Lua próbuje znaleźć pole getMagicNumber w tabeli obj. Ponieważ ta tabela jest pusta, teraz przeszukuje tabelę __index (myClass) dla tego pola. Ponieważ pole tam się znajduje, teraz wywołuje funkcję znalezioną w myClass.

Programming in Lua omawia ten mechanizm bardzo szczegółowo, jeśli chcesz dowiedzieć się więcej.

1

Nie jesteś sam, zajęło mi sporo czasu, aby zignorować ten kod.Oto moja interpretacja: każda tabela może mieć wartość netatable, metatable może przechowywać między innymi funkcje indeksowane przez nazwę, a setmetatable naturalnie ustawia wartość metatable.

Linia class._index = .. to miejsce, w którym dzieje się magia.

Podczas próby wywołania funkcji za pomocą self.fn1(), Następnie lua wyszukuje w sobie nazwę fn1. Jeśli nie może go znaleźć, to wygląda na samozatrudnione dla tabeli __index i szuka "fn1" w przechowywanej tam tabeli.

Teraz metatable dla siebie w twoim przykładzie to klasa, więc lua szuka wpisu __index w metatable (klasa), aby sprawdzić, czy istnieje funkcja o nazwie fn1 w tej tabeli, i istnieje, więc jest zwracana. Musisz ustawić __index dla klasy z powrotem do siebie, aby lua wyglądała w tym samym metatable - mylącym hej.

(odkładanie zadania na __indeks musi się odbywać tylko raz, ale z jakiegoś powodu zawsze jest wykonywane w nowym operatorze we wszystkich przykładach lua - wyjmuję go poza nowe na moich zajęciach - oszczędza kilka cykli)

Następnie zwraca się nową tabelę o, lua jest zbiorem śmieci, więc zwrot lokalny tworzy nowy stół za każdym razem.

function newInstance (class) 
    local o = {} 
    setmetatable (o, class) 
    class.__index = class 
    return o 
end 

HTH

Powiązane problemy