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
相关产品推荐
相关产品推荐

