在 LUA 中克隆对象

Clone object in LUA

我有下一个代码,我正在尝试创建对象测试的副本:

local Test = {} do
    local var1, var2 = {}

    function Test:Init(val1, val2, val3)
        var1.val1 = val1
        var1.val2 = val2
        var1.val3 = val3
    end

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

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

然后我像这样创建我的对象:

local obj1 = Test:New()
obj1:Init('a','b','c')
local obj2 = Test:New()
obj2:Init('c','d','e')

obj1:Print()
obj2:Print()

结果将是这样的:

c, d, e
c, d, e

如您所见,方法 New 没有正确克隆对象并且共享同一个实例。我究竟做错了什么?我以前没有克隆过对象,但在理解如何克隆时遇到了问题。 我从这里得到了代码:https://www.lua.org/pil/16.2.html

谢谢。

出现问题是因为您只是更改了局部变量,而不是对象本身。

当您执行 local Test = {} do 时,您并没有对 Test 对象做太多事情,您只是在创建 table 然后创建一个将立即执行的新范围,在此范围内,您有变量 var1,它将通过范围而不是对象共享。

为每个变量实现变量的正确方法实际上是在其上创建字段:

local Test = {} do    
    function Test:Init(val1, val2, val3)
        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

无论如何setmetatable它与克隆对象无关,它实现了共享行为,然后您可以使用这些行为创建任意数量的对象。