2013-03-17 40 views
2

我对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 

我在做什么错?
为什么变量主要为保留每个对象的值,但表不?
谢谢。

回答

3

您的new函数为空表设置了元表。此metatable具有功能内部数据。它还设置了一个__index metamethod。这很重要。

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

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

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

[1]部分将随后的元表的构件上执行,和一个值将从元表被存储在primaryGradient的第一个元素。

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

原因setPrimaryGradient不使用__newindex是因为它。只是不能访问self。它使用__newindex访问self["primaryGradient"];只有最后表访问获得__newindex调用。

如果要使用一些可以修改的默认值初始化您的类型,则需要复制这些值。有时你不能仅仅参考全局的。那么,你可以,但建立起来会很痛苦。

+0

这是有道理的。 谢谢Nicol! – 2013-03-17 01:18:11

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 
+0

感谢你也是叶戈尔。 – 2013-03-17 21:34:41