You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua类中__call元方法无法生效的原因是什么?

Lua中__call元方法无法触发的问题解决

你的问题出在**__call元方法的位置放错了**:你把它定义在了实例对象的元表里,而不是test这个类表的元表中。当尝试调用test()时,Lua会去查找test表的元表中的__call方法,但test本身没有设置元表,自然找不到该方法,因此报错。

你用setmetatable(self, self)是给每个实例设置元表为自身,这只会影响实例的行为(比如实例的__tostring、属性查找),和类表test能否被调用没有关系。

修复方案

直接给test类表设置元表,并把__call元方法放在这个元表里,修改后的代码如下:

test = {}
-- 给test类表设置元表,添加__call方法
setmetatable(test, {
    __call = function(cls, ...)
        print("Constructor called!")
        return cls:new(...)
    end
})

function test:new()
    local self = {}
    setmetatable(self, self)
    self.__index = self
    -- 私有属性
    local str = "hello world"
    -- 实例的元方法和公开方法
    self.__tostring = function() return "__tostring: "..str end
    self.tostring = function() return "self:tostring(): "..str end
    return self
end

local t = test:new()
print(t)             -- __tostring正常工作
print(tostring(t))   -- __tostring正常工作
print(t:tostring())  -- 公开方法正常调用
t = test()           -- 现在可以触发__call,调用构造函数

修改后的运行输出:

__tostring: hello world
__tostring: hello world
self:tostring(): hello world
Constructor called!
__tostring: hello world

这个修改完全保留了你setmetatable(self, self)的写法(确实能降低实例创建的开销),同时解决了类表无法被调用的问题。

内容的提问来源于stack exchange,提问作者Bernard Langham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 00:50:21