lua——元表、元方法、继承
【元表】 元表中的键为事件(event),称值为元方法(metamethod)。 通过函数getmetatable查询任何值的元表,通过函数setmetatable替换表的元表。 setmetatable(只能用于table)和getmetatable(用于任何对象) 【元方法】 元表可以控制对象的数学运算、顺序比较、连接、取长、和索引操作的行为。 事件: __index元方法: 【用户数据和元方法】 Userdata: 【继承】 cocos2dx里的继承: 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 end? 原理就不细说了,修改__index,使得在访问其成员的时候能遍历所有的supers父类去查找该成员(类似js里的原型链,但那是一条链,这里lua可自由发挥)。 ? 他的第一个参数是类名,后面的参数可以是父表或者函数,函数的话只能有一个,是用来作为创建函数的__create,会在.new的时候被调用。 ? 使用方法: local UIScene = class("UIScene") UIScene.__index = UIScene function UIScene.extend(target) local t = tolua.getpeer(target) if not t then t = {} tolua.setpeer(target,t) end setmetatable(t,UIScene) return target end function UIScene.create() local scene = cc.Scene:create() local layer = UIScene.extend(cc.Layer:create()) layer:init() scene:addChild(layer) return scene end? getpeer/setpeer我还不是很理解,从网上找到说明留着消化: Those are tolua functions. The tolua manual (for example here) has explanations for them. tolua.setpeer (object,peer_table) (lua 5.1 only) Sets the table as the object's peer table (can be nil). The peer table is where all the custom lua fields for the object are stored. When compiled with lua 5.1,tolua++ stores the peer as the object's environment table,and uses uses lua_gettable/settable (instead of lua_rawget/set for lua 5.0) to retrieve and store fields on it. This allows us to implement our own object system on our table (using metatables),and use it as a way to inherit from the userdata object. Consider an alternative to the previous example: -- a 'LuaWidget' class LuaWidget = {} LuaWidget.__index = LuaWidget function LuaWidget:add_button(caption) -- add a button to our widget here. 'self' will be the userdata Widget end local w = Widget() local t = {} setmetatable(t,LuaWidget) -- make 't' an instance of LuaWidget tolua.setpeer(w,t) -- make 't' the peer table of 'w' set_parent(w) -- we use 'w' as the object now w:show() -- a method from 'Widget' w:add_button("Quit") -- a method from LuaWidget (but we still use 'w' to call it) When indexing our object,the peer table (if present) will be consulted first,so we don't need to implement our own __index metamethod to call the C++ functions. tolua.getpeer (object) (lua 5.1 only) Retrieves the peer table from the object (can be nil). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |