无法从父级继承表属性

时间:2014-01-15 11:40:15

标签: oop inheritance lua lua-table

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

s1s2拥有自己的x,y属性,但如果pos发生了更改,则共享s1.pos.z属性,以及s2.pos.z

我该如何解决这个问题?

3 个答案:

答案 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