local normal_tbl = {}
normal_tbl("test1", "test2", "test3")
把 normal_tbl 表对象当作函数来使用,会怎么样?
如下图,会报错:
给 normal_tbl 添加一个元表,并给该元表对象加上 __call
local mtbl = {}
normal_tbl.__name = "normal_tbl"
mtbl.__name = "mtbl"
setmetatable(normal_tbl, mtbl)
mtbl.__call = function(self, ...)
print("self.name : " .. tostring(self.__name), ...)
end
这时候,我们再调用 normal_tbl(…)
normal_tbl("test1", "test2", "test3") -- self.name : normal_tbl test1 test2 test3
输出了对应的数值
这有什么用呢,我们可以把他当作 类蓝图对象的构造函数 来使用
实例类似 OOP
下面模拟 OOP 中有使用到 __index,可以参考:lua __index 测试
还有:
- getmetatable
- __name
等,都可以参考官方文档,不过 __name 说是 tostring() 再错误时有使用到的
但是我试过,不行!-_-!
所以我还时明文调用: tostring(tbl.__name) 来输出
-- 模拟 oop 语言 定义一个类,可以指定他的名字字段、和他的基类
function class(name, base_cls)
print("define class, name : " .. name)
if base_cls then
print(name .. " have base_cls : " .. tostring(base_cls.__name))
else
print(name .. " have no base_cls")
end
local cls = {}
local mtbl = {}
cls.__name = name
cls.__index = cls
mtbl.__name = name
mtbl.__index = base_cls -- 设置基类
mtbl.__call = function(self, ...) --[=[self 是 cls]=] return cls.new(self, ...) end
setmetatable(cls, mtbl)
-- 调用带继承层级的构造函数
function _call_ctor_inherit(cls, self, ...)
-- 递归继承的metatable
local _base_cls = getmetatable(cls)
if _base_cls then
print("check inherit ctor, in : " .. _base_cls.__name)
if _base_cls and _base_cls.__index and type(_base_cls.__index) == "table" then
_call_ctor_inherit(_base_cls.__index, self)
end
end
-- 如果有构造函数就调用
-- 这里不要使用 obj.ctor,因为可能会查找到 __index 里面去了,所以使用 rawget 来获取原始对象信息,这就可以绕过 __index 的索引查找
-- local ctor = obj.ctor
local ctor = rawget(cls, "ctor")
if ctor then
print(cls.__name .. " have ctor")
ctor(self, ...)
else
print(cls.__name .. " have no ctor")
end
end
function cls.new(self, ...)
-- self 是 cls
print(self.__name .. " __call function, with args : ", ...)
local new_obj = { __name = self.__name }
-- 给示例化对象设置类接口元表
setmetatable(new_obj, self)
-- 调用带继承层级的构造函数
_call_ctor_inherit(self, new_obj, ...)
print("return new_obj.namne :" .. new_obj.__name .. ", new_obj : " .. tostring(new_obj))
-- 返回创建的对象
return new_obj
end
-- 注意返回的是一个类
return cls
end
local HumanCls = class("HumanCls")
-- 给 HumanCls 添加 ctor 构造函数
HumanCls.ctor = function(self, ...)
print(self.__name .. ".ctor")
end
_G[HumanCls.__name] = HumanCls -- 给 "HumanCls" 注册到 _G
local TomCls = class("TomCls", HumanCls)
-- 给 TomCls 添加 ctor 构造函数
TomCls.ctor = function(self, ...)
print(self.__name .. ".ctor")
end
_G[TomCls.__name] = TomCls -- 给 "TomCls" 注册到 _G
function test_new_tom()
local tom = TomCls("arg1", "arg2")
print("tom.name : " .. tostring(tom.__name) .. ", tom : " .. tostring(tom))
end
test_new_tom()
输出:
--[=[
define class, name : HumanCls
HumanCls have no base_cls
define class, name : TomCls
TomCls have base_cls : HumanCls
TomCls __call function, with args : arg1 arg2
check inherit ctor, in : TomCls
check inherit ctor, in : HumanCls
HumanCls have ctor
HumanCls.ctor
TomCls have ctor
TomCls.ctor
return new_obj.namne :TomCls, new_obj : table: 009D2DD0
tom.name : TomCls, tom : table: 009D2DD0
]=]
然后我们将继承层级弄深一些,并且将构造函数值设置一部分,再看看结果:
-- 下面我们可以把继承层级弄深一些,并且将 .ctor 构造函数值设置一部分,再看看输出信息
local BASE_CLS = class("Base_CLS")
local CLS_A = class("CLS_A", BASE_CLS)
local CLS_B = class("CLS_B", CLS_A)
local CLS_C = class("CLS_C", CLS_B)
local CLS_D = class("CLS_D", CLS_C)
-- CLS_A、CLS_D 都不设置构造函数
CLS_B.ctor = function(self)
print("CLS_B.ctor run, inst.name : " .. self.__name)
end
CLS_C.ctor = function(self)
print("CLS_C.ctor run, inst.name : " .. self.__name)
end
local new_d = CLS_D("arg1", "arg2", "arg3")
print("new_d.cls__name : " .. new_d.__name)
再看看输出:
--[=[
define class, name : Base_CLS
Base_CLS have no base_cls
define class, name : CLS_A
CLS_A have base_cls : Base_CLS
define class, name : CLS_B
CLS_B have base_cls : CLS_A
define class, name : CLS_C
CLS_C have base_cls : CLS_B
define class, name : CLS_D
CLS_D have base_cls : CLS_C
CLS_D __call function, with args : arg1 arg2 arg3
check inherit ctor, in : CLS_D
check inherit ctor, in : CLS_C
check inherit ctor, in : CLS_B
check inherit ctor, in : CLS_A
check inherit ctor, in : Base_CLS
Base_CLS have no ctor
CLS_A have no ctor
CLS_B have ctor
CLS_B.ctor run, inst.name : CLS_D
CLS_C have ctor
CLS_C.ctor run, inst.name : CLS_D
CLS_D have no ctor
return new_obj.namne :CLS_D, new_obj : table: 009DDB88
new_d.cls__name : CLS_D
]=]