无法从父项继承表属性。

在上面的代码段中,我定义了一个名为“Sprite”的类,它有三个属性x(int),y(int),pos(table),但是当我初始化两个对象s1s2时,我发现它们共享了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也会发生改变。

如何解决这个问题?

点赞
用户107090
用户107090

Sprite:new 中,变量 self 的值始终为 Sprite。因此,self.pos 指的是 Sprite.pos。尝试改为 o.pos={}。此外,考虑将 o 改为局部变量。

2014-01-15 11:49:20
用户1601606
用户1601606

Lua 共享表格(将它们作为引用),并复制变量。使用元表进行方法,将字段复制到对象表中。

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 中找到。

2014-01-15 11:53:52
用户869951
用户869951

Sprite 代表一个类,你可以将 Sprite 表想象成“类宽”条目:它们将被所有实例共享。每个实例特有的条目应该在 o 表中:

Sprite = {classX = 0, classY = 0} -- 类;被所有实例共享的变量
function Sprite:new()
    o = {pos = {z=0}}
    setmetatable(o,self)
    self.__index = self
    return o
end

请注意,“共享”确实意味着在引用层面共享,因此所有实例都将看到相同的值,任何一个实例所做的更改都将被其他所有实例看到。另一方面,在 o 表中放置的数据是每个实例独有的。将其放置在 Sprite.new() 中可以确保所有实例都拥有相同的字段,但是它们拥有自己的数据;一个实例所做的更改不会影响到其他任何实例。

话虽如此,你的 Sprite:new() 未定义 self.__newindex。因此,Sprite.classX = 5 将被所有实例看到,如预期一样,但 s1.classX = 6 只会被 s1 看到:它将创建一个新 字段,从而隐藏 Sprite 的字段。从那时开始,对 Sprite.classX 的更改将不再被 s1 看到(但是其他没有覆盖 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”,并且对 Sprite.classX 的更改将不会在 s1 中可见。

2014-01-16 17:28:25