我想在Lua中创建一个单独的文件 myclass.lua 中的MyClass
类,我可以导入并稍后使用它。
它应该按以下方式工作:
local MyClass = require 'myclass'
tab = {1,2,3}
m = MyClass(tab)
但是,按照Lua文档中的代码,我无法正常运行并遇到错误attempt to call global 'MyClass' (a table value)
。
到目前为止我为 myclass.lua 编写的代码:
local MyClass = {}
MyClass.__index = MyClass
function MyClass.__init(tab)
self.tab = tab or {}
setmetatable({},MyClass)
return self
end
return MyClass
有很多例子如何在Lua中编写类,但我不认为我理解了这些差异,因此在实现细节中迷失了方向。是否有或多或少的传统的方式?
答案 0 :(得分:1)
在Lua中,你通常不能像调用函数一样调用表。例如,此代码将产生错误"尝试调用本地' t' (表值)"。
local t = {}
t()
然而,有一种方法可以通过使用元表来完成这项工作。
local hello = {}
local mt = {} -- The metatable
mt.__call = function ()
print("Hello!")
end
setmetatable(hello, mt)
hello() -- prints "Hello!"
当您尝试像调用函数一样调用表时,Lua首先检查表是否具有元表。如果是,则尝试在该metatable的__call
属性中调用该函数。 __call
函数的第一个参数是表本身,后续参数是表作为函数调用时传递的参数。如果表格没有metatable,或者metatable没有__call
功能,那么"尝试呼叫本地''""""""""""""""""" ;提出错误。
您的示例代码有三个问题:
__init
代替__call
。 Lua没有__init
metamethod。__call
采用的参数与您使用的参数不同。 __call
函数的第一个参数是表本身。您可以使用function MyClass.__call(self, tab)
,也可以使用冒号语法function MyClass:__call(tab)
,它会为您隐式添加self
参数。这两种语法功能相同。MyClass
表设置元表。在为MyClass的对象设置元表时,这并不意味着会自动为MyClass本身设置元表。要解决此问题,您可以执行以下操作:
local MyClass = {}
setmetatable(MyClass, MyClass)
MyClass.__index = MyClass
function MyClass:__call(tab)
local obj = {}
obj.tab = tab or {}
setmetatable(obj, MyClass)
return obj
end
return MyClass
这将MyClass设置为metatable,这是完全有效的Lua。
metatables系统非常灵活,允许您拥有所需的任何类/对象方案。例如,如果您愿意,您可以内联完成所有操作。
local MyClass = {}
setmetatable(MyClass, {
__call = function (class, tab)
local obj = {}
obj.tab = tab or {}
setmetatable(obj, {
__index = MyClass
})
return obj
end
})
return MyClass
除了简洁之外,这还有一个好处,即如果他们可以访问班级表,人们就无法改变班级的元方法。
答案 1 :(得分:0)
表格中没有__init
元方法。执行以下操作时:
m = MyClass(tab)
它查找MyClass.__call
方法定义。只需将myclass.lua
更新为:
local MyClass = {}
MyClass.__index = MyClass
function MyClass:__call(tab)
self.tab = tab or {}
setmetatable({},MyClass)
return self
end
return MyClass