也谈Lua的面相对象机制
最近闲来无事想要学习一下cocos2dx,在知乎上看到一个讨论cocos2dx + lua合适还是cocos2dx + js合适的问题,链接http://www.zhihu.com/question/21130385,看到排名第3的回答中居然把Lua的缺点列出了不支持面向对象。。。。想来我们的项目虽然没有采用cocos2dx,但是也是采用的自研引擎+Lua的模式,Lua的面相对象,几乎是比比皆是,真的是不做调研就没有发言权,希望同做开发的同仁们在对一些事物发表意见的时候多做调查,宁可不做判断也不要做出“想当然”的判定,要不Lua真的死的冤枉阿!
Lua的面相对象机制是基于metatable的,要实现类似java等面向对象语言的“类”的形式,我们定义了全局函数
function class(super, autoConstructSuper) local classType = {}; classType.autoConstructSuper = autoConstructSuper or (autoConstructSuper == nil); if super then classType.super = super; local mt = getmetatable(super); setmetatable(classType, { __index = super; __newindex = mt and mt.__newindex;}); else classType.setDelegate = function(self,delegate) self.m_delegate = delegate; end end return classType; end
用这个class实现"类",并定义父类实现继承
function super(obj, ...) do local create; create = function(c, ...) if c.super and c.autoConstructSuper then create(c.super, ...); end if rawget(c,"ctor") then obj.currentSuper = c.super; c.ctor(obj, ...); end end create(obj.currentSuper, ...); end end
当然也要实现类的构造和析构函数
function new(classType, ...) local obj = {}; local mt = getmetatable(classType); setmetatable(obj, { __index = classType; __newindex = mt and mt.__newindex;}); do local create; create = function(c, ...) if c.super and c.autoConstructSuper then create(c.super, ...); end if rawget(c,"ctor") then obj.currentSuper = c.super; c.ctor(obj, ...); end end create(classType, ...); end obj.currentSuper = nil; return obj; end function delete(obj) do local destory = function(c) while c do if rawget(c,"dtor") then c.dtor(obj); end c = getmetatable(c); c = c and c.__index; end end destory(obj); end end
这样,我们就可以轻松的通过lua实现面向对象机制,在实现子类的时候,lua编译器会通过metatable遍历其super父类找到它的构造方法,对于构造和析构都会循环这一过程直到找到它的基类,然后顺序执行构造(析构),而类的其他接口也可以实现继承,子类中定义父类的方法会覆盖,如果想要同时调用父类接口并实现子类的特定方法,只需要在接口中加入super.func(self)即可