Lua元方法改写问题:为何重写后的代码无法正常运行?
咱们来一步步拆解你改写后的代码为什么不工作,以及如何修复:
1. 你没有创建独立的实例,而且返回的是数字而非表
在你最初的代码里,tb.new()每次都会创建一个全新的super表,给它设置b属性,再把元表绑定到这个新表上——这正是每个实例能保留自己独立值的原因。
但在改写后的代码里:
tb是一个全局共享的单一表,每次调用ins(a)都会覆盖tb.a的值,后调用的会把之前的覆盖掉。- 更关键的是,
ins(a)返回的是tb.a,也就是一个数字,而不是表本身。所以当你执行ins(2)..ins(3)时,其实是在拼接两个数字2和3。Lua中..对数字的默认行为是把它们转成字符串再拼接,结果会是"23",完全不是你想要的相加逻辑。
2. 你的__concat元方法绑定错了对象
你把__concat定义在了tb这个表上,但你在拼接时根本没用到tb作为实例。你传给..的是数字,数字使用的是Lua默认的数字元表,根本不会调用你自定义的__concat方法。
正确的改写版本
我们需要回到“为每个值创建独立表实例”的逻辑,并且把元表绑定到每个实例上:
-- 定义包含__concat逻辑的元表 local instanceMeta = { __concat = function(a, b) return a.value + b.value end } -- 创建实例的函数 local function ins(a) -- 为每个实例创建新表,存储对应的值 local newInstance = {value = a} -- 把元表绑定到这个新实例上 setmetatable(newInstance, instanceMeta) return newInstance end -- 测试代码 local f = ins(2) local t = ins(3) print(f .. t) -- 现在会输出5,符合预期!
为什么这个版本能工作:
- 每次调用
ins()都会生成一个全新的表,每个实例都能保留自己的数值,不会互相覆盖。 - 我们把带有自定义
__concat的元表绑定到了每个实例表上。当对两个实例表使用..时,Lua会从它们的元表中找到__concat方法,执行我们定义的相加逻辑。
内容的提问来源于stack exchange,提问作者Xuer




