lua实现类有很多种写法,一般主流的实现方式是使用lua的元表来实现。下面举一个例子来详细解释其原理
--[[
模拟class的几大基本需求
1. 支持对象调用成员方法和成员变量
可以通过 obj:method(...) 调用 class 的函数
注:obj:method(...) 等同于 obj.method(self, ...)
但是 obj 内部不应该持有 method
obj.method 该变量来源应该至少为 getmetatable(obj).__index.method
先假定 class == getmetatable(obj).__index
这步 obj 初始化步骤为
mtObj.__index = class
setmetatable(obj, mtObj)
在 class 里实现的 method,需要调用成员变量时只需要写上 self,则必然引用的是 obj 表里的变量
2. 支持类实例化对象时调用构造函数
可以通过 class.new(...) 生成一个 obj ,调用 obj:ctor() 并返回 obj
a)如果写成 class 表内部不包含 new 的形式(这种写法是错误的)
class.new 该变量来源应该至少为 getmetatable(class).__index.new
obj:ctor() 为 obj.ctor(self, ...)
obj.ctor 该变量来源应为 class.ctor == getmetatable(obj).__index.ctor
这步 class 初始化步骤为
local class = {}
class.ctor = function ()
-- empty function
end
local mtClassIndex = {}
mtClassIndex.new = function (...)
local obj = {}
local mtObj = {}
-- 这里是上一步得出的结论
mtObj.__index = class
setmetatable(obj, mtObj)
obj:ctor(...)
return obj
end
mtClass.__index = mtClassIndex
setmetatable(class, mtClass)
(后面会详细说明为什么是错的)
b)如果写成 class 表内部包含 new 的形式
直接可以写成
class.new = function (...)
local obj = {}
local mtObj = {}
mtObj.__index = class
setmetatable(obj, mtObj)
obj:ctor(...)
return obj
end
3. 支持类的继承和多态性
a) obj:baseMethod 它的类没有这个方法时,调用父类的方法(类的继承性)
class 里没有 baseMethod
obj.baseMethod 的数据来源为 getmetatable(class).__index.baseMethod
先假定 class._base == getmetatable(class).__index
这里 class 应初始化为
class._base = base
mtClass.__index = base
setmetatable(class, mtClass)
b) obj:derivedMethod 它的类有这个方法,调用子类的方法(优先实现虚拟继承,类的多态性)
obj.derivedMethod 数据来源为 class,cl