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

Lua自定义New方法克隆对象出现实例数据共享问题如何解决

问题成因

你代码的核心错误是将所有实例的公共数据存到了Test闭包的局部变量var1中,这个变量是Test所有实例共享的,每次调用Init方法都会覆盖同一个var1的属性,和New方法本身的逻辑无关。
Lua面向对象实现中,每个实例独有的属性必须存储在实例自身的table(也就是方法调用时的self变量指向的table)中,不能存在类的upvalue里。

修正后的实现

基础版本(仅独立存储实例属性)

local Test = {} do
    function Test:Init(val1, val2, val3)
        -- 属性直接存储在当前实例self中,每个实例的self是独立的table
        self.val1 = val1
        self.val2 = val2
        self.val3 = val3
    end

    function Test:Print()
        print(self.val1)
        print(self.val2)
        print(self.val3)
    end

    function Test:New(obj)
        obj = obj or {}
        setmetatable(obj, self)
        self.__index = self
        return obj
    end
end

测试代码无需修改,运行后输出符合预期:

a
b
c
c
d
e

带深拷贝的克隆实现

如果需要基于已有实例克隆出完全独立的副本,需要补充深拷贝逻辑处理嵌套table的情况:

-- 通用深拷贝函数
local function deepCopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for k, v in next, orig, nil do
            copy[deepCopy(k)] = deepCopy(v)
        end
        setmetatable(copy, deepCopy(getmetatable(orig)))
    else
        copy = orig
    end
    return copy
end

-- 给Test类新增克隆方法
function Test:Clone()
    return deepCopy(self)
end

使用示例:

local obj1 = Test:New()
obj1:Init('a','b','c')
local obj_clone = obj1:Clone()
obj_clone.val1 = '修改后的值'
print(obj1.val1) -- 输出a,原实例不受影响
print(obj_clone.val1) -- 输出修改后的值,克隆实例独立

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:18:04