2016-10-13 31 views
2

試圖創建一個非常簡單的類繼承,所有對象似乎是共享相同的價值觀Lua的對象不是唯一的

這是我的代碼的簡化:

--Generic class 
Object = {} 

function Object:new (type,id,name) 
    o = {} 
    self.type = type or "none" 
    self.id = id or 0 
    self.name = name or "noname" 
    self.direction = "down" 
    self.animations = {} 
    self.animations.stack = {} 
    self.animations.idle = {} 
    self.animations.idle[self.direction] = {} 
    setmetatable(o, self) 
    self.__index = self 
    return o 
end 

function Object:draw(x,y) 
    local img = self.animations.idle["down"][0] 
    print("drawing " ..self.name.." as "..img) 
end 

function Object:setimg(img) 
    self.animations.idle["down"][0] = img 
end 

Player = Object:new() 

-- Player class 
function Player:new(id,name) 
    local o = self 

    o.id = id or 0 
    o.name = name or "noname" 

    o.collision = {} 
    o.collision.type = "player" 

    return o 
end 

function Player:move(x,y) 
    print("moving to ",x,y) 
end 

-- Testing 
blockimg = "block.png" 
grassimg = "grass.png" 
plyrimg = "player.png" 

block = Object:new("solid",1,"block") 
block:setimg(blockimg) 

grass = Object:new("floor",3,"grass") 
grass:setimg(grassimg) 

player = Player:new(1, "plyr1") 
player:setimg(plyrimg) 

block:draw() -- >drawing grass as player.png 
grass:draw() -- >drawing grass as player.png 
player:draw()-- >drawing plyr1 as player.png 

由於球員:setimg是最後一次調用的所有「對象」以plyrimg結束,因此它們不是唯一的

回答

2

此函數在每次創建新對象實例時都在共享對象表上創建或覆蓋屬性。

function Object:new (type,id,name) 
    o = {} 
    self.type = type or "none" 
    self.id = id or 0 
    self.name = name or "noname" 
    self.direction = "down" 
    self.animations = {} 
    self.animations.stack = {} 
    self.animations.idle = {} 
    self.animations.idle[self.direction] = {} 
    setmetatable(o, self) 
    self.__index = self 
    return o 
end 

如果您希望它們是唯一的,您需要在每個新實例上創建這些屬性。否則,Object:setimg將查找索引鏈找到animations,並將圖像放入共享屬性中。

function Object:new (type,id,name) 
    local o = {} 
    -- ... 
    o.animations = {} -- Or in Player:new 
    -- ... 
    self.__index = self 
    return setmetatable(o, self) 
end 
+0

該死的我真的不明白,在構造函數中啓動表沒有意義? – Mojimi

+0

這並非毫無意義!你只需要注意你在'構造函數'中分配的_which_表 - 記住在'new'中,'self'在被稱爲'Player:new'或'Object:new'時引用_class_而不是_instance_, 。 – Oka

+0

AAAAAAAAAAAAHHHHHHHHHH我看到了,現在我明白了,謝謝 – Mojimi

0

如果您不簡單地將自我傳遞給構造函數,就可以避免很多問題。我通常定義類這樣的:

local class={x=0,y=0} 
local _class={__index=Class} 
-- I like prefixing metatables with _, but that's just a personal thing 
class.new(x, y) 
    return setmetatable({x=x, y=y}, _class) 
end 
class:print() print(self.x, self.y) end 
class.sub(sub) return getmetatable(sub)==_class end 

這是假設類是無論是在自己的文件或在do塊,以保持隱藏任何東西,但類及其封閉的局部變量。

你可以在github上的lua文檔中閱讀更多關於這方面的內容。