Lua表变量即使对于新对象也是相同的

Lua表变量即使对于新对象也是相同的,lua,Lua,我试图创建一个表示矩阵的Lua表,但是我一直遇到一个问题,如果我创建两个矩阵,并初始化一些值,它们都有相同的值 --Test.Lua require"Matrix" M1 = Matrix.Matrix:New() M2 = Matrix.Matrix:New() M1._11 = 2 print(M1._11) --Prints 2 print(M2._11) --Prints 2 --Matrix.lua module("Matrix", package.seeall) Mat

我试图创建一个表示矩阵的Lua表,但是我一直遇到一个问题,如果我创建两个矩阵,并初始化一些值,它们都有相同的值

--Test.Lua
require"Matrix"

M1 = Matrix.Matrix:New()
M2 = Matrix.Matrix:New()

M1._11 = 2

print(M1._11) --Prints 2
print(M2._11) --Prints 2


--Matrix.lua

module("Matrix", package.seeall)

Matrix = {}

Matrix = {  _11 = 0, _12 = 0, _13 = 0,
        _21 = 0, _22 = 0, _23 = 0,
        _31 = 0, _32 = 0, _33 = 0
    }

function Matrix:New()
    object = object or {}
    setmetatable(object, self)
    self.__index = self
    return object
end 
这就是为什么会发生这种情况。只能创建一个矩阵对象。您返回的每个
对象
表只有一个,而您用作元表的
self
表也只有一个

那么,当
Matrix:New
每次调用都返回完全相同的值时,您怎么能期望不同的实例呢

您需要为每个
new
调用返回一个新表;这就是为什么我们用这个名字;)由于使用元表的方式,还必须返回一个新的元表;不能返回附加到新表的同一元表并期望它工作

这就是为什么会发生这种情况。只能创建一个矩阵对象。您返回的每个
对象
表只有一个,而您用作元表的
self
表也只有一个

那么,当
Matrix:New
每次调用都返回完全相同的值时,您怎么能期望不同的实例呢


您需要为每个
new
调用返回一个新表;这就是为什么我们用这个名字;)由于使用元表的方式,还必须返回一个新的元表;您不能返回附加到新表的同一元表并期望它工作。

正如nicol所解释的,一方面您试图“反复使用同一对象”(可能是为了“使其更快”),另一方面您希望拥有不同的对象

解决方案是-不要在新调用时重用
对象

local Matrix = {} -- don't use the module function. Make Matrix local ...
Matrix.__index = Matrix

function Matrix:New()
    local object = { -- create one local variable on every call to New
        _11 = 0, _12 = 0, _13 = 0,
        _21 = 0, _22 = 0, _23 = 0,
        _31 = 0, _32 = 0, _33 = 0
    }   
    setmetatable(object, self)
    return object
end

return Matrix -- ... and return the Matrix local var at the end
几点注意:

  • 你真的必须学会如何使用
    local
  • 不建议使用模块功能。而是返回一个本地表,如我的示例中所示
用法:假设该文件名为“Matrix.lua”:

作为旁注,
Matrix:New()
函数可以更短(更快)。以下实现与上面的实现完全相同,但效率稍高一些:

function Matrix:New()
    return setmetatable({
        _11 = 0, _12 = 0, _13 = 0,
        _21 = 0, _22 = 0, _23 = 0,
        _31 = 0, _32 = 0, _33 = 0
    },
    self)
end

这是因为
setmetatable(t,m)
返回
t
,而
m
已经设置为其元表。

正如nicol所解释的,一方面,您试图“反复使用相同的对象”(可能是为了“使其更快”),另一方面,您希望拥有不同的对象

解决方案是-不要在新调用时重用
对象

local Matrix = {} -- don't use the module function. Make Matrix local ...
Matrix.__index = Matrix

function Matrix:New()
    local object = { -- create one local variable on every call to New
        _11 = 0, _12 = 0, _13 = 0,
        _21 = 0, _22 = 0, _23 = 0,
        _31 = 0, _32 = 0, _33 = 0
    }   
    setmetatable(object, self)
    return object
end

return Matrix -- ... and return the Matrix local var at the end
几点注意:

  • 你真的必须学会如何使用
    local
  • 不建议使用模块功能。而是返回一个本地表,如我的示例中所示
用法:假设该文件名为“Matrix.lua”:

作为旁注,
Matrix:New()
函数可以更短(更快)。以下实现与上面的实现完全相同,但效率稍高一些:

function Matrix:New()
    return setmetatable({
        _11 = 0, _12 = 0, _13 = 0,
        _21 = 0, _22 = 0, _23 = 0,
        _31 = 0, _32 = 0, _33 = 0
    },
    self)
end

这是因为
setmetatable(t,m)
返回
t
,其中
m
已经设置为其元表。

哦,好吧,我从Lua编程中获得了这个新方法,可能我没有正确实现它。我该如何解决这个问题?@RedShft:我建议回顾一下“Lua中的编程”,了解它在做什么以及为什么要这么做,而不仅仅是复制和粘贴代码。它使用的元表中没有一个是像您使用的那样使用的(对于PIL,它是存储数据的对象;元表只存储某些函数等等)。此外,PIL的
new
函数可选地将对象作为参数;这就是为什么他们做了
o=o或{}
的事情。您的函数只是使用了一个名为
object
的全局变量,因为您忘记将
object
作为参数。请注意,这并不能解决您的问题。您拒绝向我解释吗?好的。哦,好的,我从Lua编程中得到了这个新方法,也许我没有正确地实现它。我该如何解决这个问题?@RedShft:我建议回顾一下“Lua中的编程”,了解它在做什么以及为什么要这么做,而不仅仅是复制和粘贴代码。它使用的元表中没有一个是像您使用的那样使用的(对于PIL,它是存储数据的对象;元表只存储某些函数等等)。此外,PIL的
new
函数可选地将对象作为参数;这就是为什么他们做了
o=o或{}
的事情。您的函数只是使用了一个名为
object
的全局变量,因为您忘记将
object
作为参数。请注意,这并不能解决您的问题。您拒绝向我解释吗?好啊