Sprite = {x = 0, y = 0, pos = {z=0}}
function Sprite:new()
o = {}
setmetatable(o,self)
self.__index = self
return o
end
s1 = Sprite:new()
s2 = Sprite:new()
s1.x = 10
s1.pos.z = 5
print("s1.x", s1.x, "s2.x", s2.x, "s1.z",s1.pos.z, "s2.z", s2.pos.z )
s2.x = 20
s2.pos.z = 50
print("s1.x", s1.x, "s2.x", s2.x, "s1.z",s1.pos.z, "s2.z", s2.pos.z )
在上面的代码片段中,我定义了一个具有Sprite
3个属性的类x(int),y(int),pos(table)
,但是当我初始化两个对象s1,s2
时。我发现他们分享了pos
属性。
如果您运行代码,它将打印:
s1.x 10 s2.x 0 s1.z 5 s2.z 5
s1.x 10 s2.x 20 s1.z 50 s2.z 50
s1
和s2
拥有自己的x,y
属性,但如果pos
发生了更改,则共享s1.pos.z
属性,以及s2.pos.z
我该如何解决这个问题?
答案 0 :(得分:3)
在Sprite:new
中,变量self
始终以Sprite
作为其值。因此,self.pos
指的是Sprite.pos
。尝试更改为o.pos={}
。另外,请考虑将o
设为本地。
答案 1 :(得分:0)
Sprite表示类,因此您可以将Sprite表视为“类范围”条目:它们将由所有“实例”共享。特定于实例的条目应该在o表中:
Sprite = {classX = 0, classY = 0} -- class; vars shared by all instances
function Sprite:new()
o = {pos = {z=0}}
setmetatable(o,self)
self.__index = self
return o
end
请注意,“shared”确实意味着在引用级别共享,因此所有实例都将看到相同的值,并且所有其他实例将看到一个实例所做的任何更改。您放入表中的OTOH数据是每个实例。将它放在Sprite.new()中可以确保所有实例都具有相同的字段,但是它们自己的数据;一个实例的更改不会影响任何其他实例。
那就是说,你的Sprite:new()没有定义self .__ newindex。因此,所有实例都会看到Sprite.classX = 5,正如预期的那样,但s1.classX = 6只会被s1看到:它会创建一个新字段,从而隐藏Sprite的字段。从那时起,s1将不再看到对Sprite.classX的更改(但是所有其他未覆盖Sprite.classX的实例将会看到)。要解决这个问题,你可以这样做:
function Sprite:new()
o = {pos = {z=0}}
setmetatable(o,self)
self.__index = self
self.__newindex = self
return o
end
在Lua控制台中,你会看到这个,如果你玩这个:
> s1=Sprite:new()
> s2=Sprite:new()
> print(s1.classX, s2.classX)
0 0
> Sprite.classX=1
> print(s1.classX, s2.classX)
1 1
> s1.classX=3
> print(s1.classX, s2.classX)
3 3
如果没有更改,最后一个输出将显示“3 1”,并且在s1中将无法看到对Sprite.classX的更改。
答案 2 :(得分:-1)
Lua共享表(保留它们作为参考),并复制变量。将metatable用于方法,并将字段保存在对象表中。
Sprite = {
instanceData = { x = 0, y = 0, pos = {z = 0} },
method = function(self) print("do smth with "..self) end
}
function Sprite:new()
local o = deepCopy(self.instanceData)
setmetatable(o,self)
self.__index = self
return o
end
可以找到深层复制实施wiki/CopyTable