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