更改对象中table的值会更改所有对象的值。如何让它只为特定对象更改它?

时间:2013-03-17 00:50:09

标签: lua

我对Lua中的物体知之甚少,所以请耐心等待 示例代码:

Colors = {  
        primary = "BF2626",   
        primaryGradient = {"CC2929", "B32424"}
        }

function Colors:new(o)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  return o
end

function Colors:setPrimaryGradient()
  self.primaryGradient[1] ="Changed"
end

function Colors:setPrimary()
  self.primary ="00FF00"
end

a =Colors:new()
b =Colors:new()

b:setPrimaryGradient()
b:setPrimary()

print(a.primaryGradient[1])
print(b.primaryGradient[1])
print(a.primary)
print(b.primary)  

输出:

Changed
Changed
BF2626
00FF00

我做错了什么? 为什么变量 primary 为每个对象保留其值,但表没有?
感谢。

2 个答案:

答案 0 :(得分:3)

您的new函数为空表设置元表。此metatable具有函数的内部数据。它还设置了__index元方法。这很重要。

您的setPrimaryGradient方法将self作为隐式参数。在这种情况下,self是在new中创建的新表。你的问题在这里:

self.primaryGradient[1]不是一个单独的构造。它是两个独立的操作。让我们写出Lua如何使用它:self["primaryGradient"][1]。看到问题了?

第一部分self["primaryGradient"]将检查self表并获取primaryGradient成员。问题是因为self有一个__index元方法,并且primaryGradient中没有self成员,因此它会直接使用__index元方法。因此它将从metatable 获取primaryGradient 。一个共享的元表

然后将在metatable的成员上执行[1]部分,并且值将存储在metatable primaryGradient 的第一个元素中。

setPrimary没有出现同样问题的原因很简单。 self.primary是一项操作。因为它是一个表访问,后跟一个赋值操作,所以Lua不会使用__index元方法。它将改为使用__newindex元方法。由于您没有为self的metatable定义一个,它将使用默认逻辑:在self中创建一个新成员并设置其值。

setPrimaryGradient不使用__newindex的原因是因为它。只是不能访问self。它使用__newindex访问self["primaryGradient"];只有 last 表访问才能获得__newindex电话。

如果要使用可以修改的某些默认值初始化类型,则需要复制这些值。你有时不能只参考全球的。嗯,你可以,但设置起来会很痛苦。

答案 1 :(得分:1)

可以通过这种方式轻松解决问题:

Colors = {  
        primary = "BF2626",   
        primaryGradient = {"CC2929", "B32424"}
        }
Colors.primaryGradient.__index = Colors.primaryGradient

function Colors:new(o)
  o = o or {primaryGradient = setmetatable({}, self.primaryGradient)}
  setmetatable(o, self)
  self.__index = self
  return o
end