2014-01-15 135 views
2
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具有x(int),y(int),pos(table) 3個屬性,但是當我的init 2個對象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

我該如何解決這個問題?

回答

-1

Lua共享表(保留它們作爲參考)和複製變量。爲方法使用metatables,並將字段複製到對象表中。

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

+0

'self .__ index = self'應該在'Sprite:new'之外完成。 – lhf

+0

但是,如果您從類中複製所有數據,「__index」的用途是什麼?它永遠不會被調用。 – lhf

+0

@lhf我只複製字段值(instanceData)。沒有必要複製方法,所以metatable對他們更好。這將是更清晰的解決方案,創建類表,但它是一個簡單的例子。也許我會在稍後提供。 – Seagull

3

Sprite:new中,變量self始終具有Sprite作爲其值。所以,self.pos是指Sprite.pos。嘗試更改爲o.pos={}。另外,考慮將o設爲本地。

0

雪碧表示類,因此你能想到的雪碧表作爲「級寬」條目:他們將所有的「實例」共享。例如特定條目應在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 

需要注意的是「共享」,確實意味着在基準水平共享,因此所有實例將看到相同的價值觀,並通過一個實例所做的任何更改將被視爲所有其他人。您放在o表中的OTOH數據是每個實例。將它放在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中不可見。