在Lua中,我們可以通過table+function來模擬實現類。 而要模擬出類,元表(metatable)和__index元方法是必不可少的。 為一個表設置元表的方法: table = {} metatable = {} setmetatable(table, metatable) 或者 tabl ...
在Lua中,我們可以通過table+function來模擬實現類。
而要模擬出類,元表(metatable)和__index元方法是必不可少的。
為一個表設置元表的方法:
table = {}
metatable = {}
setmetatable(table, metatable)
或者
table = setmetatable({},{})
下麵看一個簡單的例子:
local t = { k1 = "aaa" } local mt = { k2 = "bbb", __index = { k3 = "ccc" } } setmetatable(t, mt) print("k1:", t.k1, "k2:", t.k2, "k3:", t.k3)
輸出:
k1: aaa k2: nil k3: ccc
從例子可以看出,查找表元素時會從表的元表的__index鍵中查找。
查找一個表元素的規則如下:
1.在表中查找,如果找到,返回該元素;如果找不到,繼續2 2.判斷該表是否有元表,如果沒有,返回nil;如果有,繼續3 3.判斷元表中是否有__index方法, 如果__index方法為nil,返回nil; 如果__index方法是一個表,則重覆 1,2,3; 如果__index方法是一個函數,則返回該函數的返回值。
除了有__index元方法外,還有__newindex,__add,__sub等很多原方法,可查看Lua文檔
2.4 – Metatables and Metamethods
在瞭解了元表和元方法後,我們就可以模擬類的實現了。
local A = { a1 = "this is a1", a2 = 100 } function A.new() local o = {} setmetatable(o, A) A.__index = A return o end function A:Print() print("This is A:Print ") end local a = A.new() a:Print()
輸出結果:
This is A:Print
以上就是一個類的簡單實現方式,當然,我們也可以把它的實現封裝到一個function中,這樣會更方便我們類的創建和使用。
下麵是cocos2d引擎中,lua類的實現,以供參考:
local setmetatableindex_ setmetatableindex_ = function(t, index) if type(t) == "userdata" then local peer = tolua.getpeer(t) if not peer then peer = {} tolua.setpeer(t, peer) end setmetatableindex_(peer, index) else local mt = getmetatable(t) if not mt then mt = {} end if not mt.__index then mt.__index = index setmetatable(t, mt) elseif mt.__index ~= index then setmetatableindex_(mt, index) end end end setmetatableindex = setmetatableindex_ function class(classname, ...) local cls = {__cname = classname} local supers = {...} for _, super in ipairs(supers) do local superType = type(super) assert(superType == "nil" or superType == "table" or superType == "function", string.format("class() - create class \"%s\" with invalid super class type \"%s\"", classname, superType)) if superType == "function" then assert(cls.__create == nil, string.format("class() - create class \"%s\" with more than one creating function", classname)); -- if super is function, set it to __create cls.__create = super elseif superType == "table" then if super[".isclass"] then -- super is native class assert(cls.__create == nil, string.format("class() - create class \"%s\" with more than one creating function or native class", classname)); cls.__create = function() return super:create() end else -- super is pure lua class cls.__supers = cls.__supers or {} cls.__supers[#cls.__supers + 1] = super if not cls.super then -- set first super pure lua class as class.super cls.super = super end end else error(string.format("class() - create class \"%s\" with invalid super type", classname), 0) end end cls.__index = cls if not cls.__supers or #cls.__supers == 1 then setmetatable(cls, {__index = cls.super}) else setmetatable(cls, {__index = function(_, key) local supers = cls.__supers for i = 1, #supers do local super = supers[i] if super[key] then return super[key] end end end}) end if not cls.ctor then -- add default constructor cls.ctor = function() end end cls.new = function(...) local instance if cls.__create then instance = cls.__create(...) else instance = {} end setmetatableindex(instance, cls) instance.class = cls instance:ctor(...) return instance end cls.create = function(_, ...) return cls.new(...) end return cls endView Code