Oop Can';t从父级继承表属性

Oop Can';t从父级继承表属性,oop,inheritance,lua,lua-table,Oop,Inheritance,Lua,Lua Table,在上面的代码片段中,我定义了一个类Sprite,它有x(int)、y(int)、pos(table)3个属性,但是当我初始化两个对象s1、s2时。我发现他们共享pos属性 如果运行代码,它将打印: Sprite = {x = 0, y = 0, pos = {z=0}} function Sprite:new() o = {} setmetatable(o,self) self.__index = self return o end s1 = Sprite:new

在上面的代码片段中,我定义了一个类
Sprite
,它有
x(int)、y(int)、pos(table)
3个属性,但是当我初始化两个对象
s1、s2
时。我发现他们共享
pos
属性

如果运行代码,它将打印:

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 )
s1
s2
都有自己的
x,y
属性,但是如果
s1.pos.z
被更改,则共享
pos
属性,从而
s2.pos.z


如何修复此问题?

Sprite:new
中,变量
self
始终将
Sprite
作为其值。所以,
self.pos
指的是
Sprite.pos
。尝试更改为
o.pos={}
。此外,考虑制作<代码> o>代码>本地的.< /p> Lua共享表(保持它们作为引用),并复制变量。对方法使用元表,并保持字段在对象表中复制它们

s1.x    10  s2.x    0   s1.z    5   s2.z    5
s1.x    10  s2.x    20  s1.z    50  s2.z    50

可以找到深度复制实现

Sprite表示类,因此您可以将Sprite表视为“类范围”条目:它们将由所有“实例”共享。特定于实例的条目应位于o表中:

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
请注意,“共享”实际上意味着在引用级别共享,因此所有实例都将看到相同的值,一个实例所做的任何更改都将被所有其他实例看到。您放在o表中的数据是每个实例的。将其放入Sprite.new()中可确保所有实例都有相同的字段,但有自己的数据;一个实例所做的更改不会影响任何其他实例

也就是说,您的Sprite:new()并不定义self.\uu newindex。因此,所有实例都会看到Sprite.classX=5,正如预期的那样,但是s1.classX=6只会被s1看到:它将创建一个新字段,从而隐藏Sprite的字段。从那时起,对Sprite.classX的更改将不再被s1看到(但将被所有其他未覆盖Sprite.classX的实例看到)。要解决这个问题,您可以这样做:

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
在Lua控制台中,如果您使用以下内容,您将看到:

function Sprite:new()
    o = {pos = {z=0}}
    setmetatable(o,self)
    self.__index = self
    self.__newindex = self
    return o
end

如果没有该更改,最后的输出将显示“3 1”,对Sprite.classX的更改在s1中将不可见

但是如果您从类中复制所有数据,
\uu index
有什么作用?它永远不会被调用。@lhf我只复制字段值(instanceData)。不需要复制方法,所以metatable更适合它们。这将是一个更清晰的解决方案,创建类表,但这只是一个简单的示例。也许我以后会提供。(在)Seagull@lhf-Thax为您快速回复,它似乎是书写时唯一的副本属性。因此,表(引用)被共享。@ USE96860还查看了大量的LuaOOP实现,如果您想要快速可靠的结果,请考虑使用其中之一。为了便于学习,这里还有一些资料。
> 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