Lua面向对象的简易实现
最近几天看到朋友写的Lua脚本,之前自己用的是cocos2d-x,突然想到原生的Lua是没有面向对象这个概念的,如果能给Lua加上面向对象的一个框架那对程序员来说肯定能方便很多。
首先要确认一下我们需要实现的效果,面向对象的三个特性,封装、继承、多态。封装对于Lua而言其实就是把一些变量和函数,存在Lua的table中,这样在访问这个table的时候就可以访问到这些函数需要注意的是,lua的table是一个开放的表,没有private和protected权限,继承我们则可以通过Lua的元方法来实现,多态由于Lua弱类型的特点无法实现。
因此我们需要实现的效果是,在new一个类时,如果当前类具有这个函数,则调用,如果当前类没有,则查找其父类是否具有该函数,这样递归直到该类没有其父类为止,则返回一个nil。
一个子类如果继承了一个类,则该子类拥有父类的相关方法,并且可以调用父类的方法,如果子类中有同名函数,则重写这个方法,下次调用的时候会调用子类的函数,而不是父类的同名函数。
那这里我们就可以通过元方法的__index和__newindex实现,首先__index指向当前类的父类,而父类的__index又指向父类的父类,因此就完成了继承和重载的效果,这里使用了__newindex是为了能够在开发者声明new函数时能够拷贝一个当前类的对象使用,子类可以通过super显式调用其父类
// An highlighted block
local function class(curClass,super)
curClass = {}
local curClassMeta = {}
local tlClassValue = {}
local function newClassFunc()
local tClass = {}
setmetatable(tClass,curClassMeta)
return tClass
end
curClass.super = super
curClassMeta.__index = function(_,key)
local superClass = tlClassValue[key]
if (not superClass) and super then
superClass = super[key]
end
return superClass
end
curClassMeta.__newindex = function(table,key,value)
if key == "new" then
tlClassValue[key] = function(params)
//这个地方不能直接给table赋值,需要新建一个临时的table用于存储,否则会循环调用当前table的__newindex元方法会报错。
local t = newClassFunc()
value(t,params)
return t
end
else
tlClassValue[key] = value
end
end
setmetatable(curClass,curClassMeta)
return curClass
end
测试代码
local a = class(...)
function a:new()
self.a = 1
end
function a:funcA()
print("1111")
end
local b = class(...,a)
function b:new(str)
b.super.new(self)
self.a = str
end
function b:funcA()
print(self.a)
print(self)
print("BBBB")
end
local c = class(...,b)
-- function c:funcA()
-- print("CCCC")
-- end
local c1 = c.new()
c1:funcA()
local b1 = b.new("aaa")
b1:funcA()
输出为
1
表地址
BBBB
aaa
表地址
BBBB
最后需要注意的是新的子类必须要重写new否则会申请父类的表,调用时会调用父类的函数而不是当前子类的函数