上面我們看到有__index這個重載,這個東西主要是重載了find key的操作。這操作可以讓Lua變得有點面向對象的感覺,讓其有點像Javascript的prototype。
所謂__index,說得明確一點,如果我們有兩個對象a和b,我們想讓b作爲a的prototype只需要:
setmetatable(a, {__index = b})
例如下面的示例:你可以用一個Window_Prototype的模板加上__index的MetaMethod來創建另一個實例:
Window_Prototype = {x=0, y=0, width=100, height=100}
MyWin = {title="Hello"}
setmetatable(MyWin, {__index = Window_Prototype})
於是:MyWin中就可以訪問x, y, width, height的東東了。(注:當表要索引一個值時如table[key], Lua會首先在table本身中查找key的值, 如果沒有並且這個table存在一個帶有__index屬性的Metatable, 則Lua會按照__index所定義的函數邏輯查找)
有了以上的基礎,我們可以來說說所謂的Lua的面向對象。
Person={}
function Person:new(p)
local obj = p
if (obj == nil) then
obj = {name="ChenHao", age=37, handsome=true}
end
self.__index = self
return setmetatable(obj, self)
end
function Person:toString()
return self.name .." : ".. self.age .." : ".. (self.handsome and "handsome" or "ugly")
end
上面我們可以看到有一個new方法和一個toString的方法。其中:
1)self 就是 Person,Person:new(p),相當於Person.new(self, p)
2)new方法的self.__index = self 的意圖是怕self被擴展後改寫,所以,讓其保持原樣
3)setmetatable這個函數返回的是第一個參數的值。
於是:我們可以這樣調用:
me = Person:new()
print(me:toString())
kf = Person:new{name="King's fucking", age=70, handsome=false}
print(kf:toString())
繼承如下,我就不多說了,Lua和Javascript很相似,都是在Prototype的實例上改過來改過去的。