2013-03-01 73 views
2

我的直覺告訴我,我犯了一個明顯的錯誤,但它逃避了我。我試圖通過使用以下示例代碼來從指定的「父」對象中創建「子」對象。Lua和對象產卵

local Ad = { 
    __index = Ad, 
    __tostring = function(self) return self.msg end, 
    __concat = function(a, b) return tostring(a)..tostring(b) end, 
    Initialize = function(self, msg, wgt) 
     if msg and msg ~= "" then 
      wgt = wgt or 1 
      self.msg, self.wgt, self.ranLog = msg, wgt, {} 
     end 
    end, 
    Increase = function(self) 
     if self.wgt < 9 then self.wgt = self.wgt + 1 end 
    end, 
    Decrease = function(self) 
     if self.wgt > 1 then self.wgt = self.wgt - 1 end 
    end 
} 

local function new(src, ...) 
    local o = setmetatable({}, src) 
    if src.Initialize then o:Initialize(...) end 
    return o 
end 

local ad = new(Ad, "Test Message") 
print("Object - "..ad) 
for k, v in pairs(ad) do print("", k, v) end 
ad:Increase() 
print("Modified Object - "..ad) 
for k, v in pairs(ad) do print("", k, v) end 

所以這是逐字與試圖調用方法初始化這是一個零值什麼失敗。鑑於在編輯之前我的示例代碼確實有效,是否已經定義了表格廣告?或者我在這裏某處有語法錯誤?

  • 編輯,以替換代碼片段與該失敗
+2

當我替換實際的代碼您的意見,這對我的作品。我認爲你太簡化了你的代碼。 – 2013-03-01 22:20:04

+0

好的,這裏是(除了我將作爲示例留下的變量名稱)更多的表格以防萬一這是問題。 – user1901873 2013-03-02 00:04:11

回答

3

問題實際代碼是這樣的:

local Ad = { 
    __index = Ad, 
    ... 
} 

在被分配的時間__indexAdnil,因爲表被構造在被分配到Ad之前。由於__index未設置,因此Initialize的查找失敗。

相反,這樣做:

local Ad = { 
    ... 
} 
Ad.__index = Ad 
+1

除非我誤解了,'Ad'不在該表的構造函數的範圍內,所以當您執行'_index = Ad'時,它實際上使用全局變量'Ad'。這也默認爲零,所以它的工作原理相同,但這意味着您可以通過更改全局環境(嚴格模式)的metatable或通過使用linter來捕獲這些錯誤。 – hugomg 2013-03-02 01:19:46

+0

是的,這是正確的。 'Ad'會導致訪問'_G.Ad',這是'nil'。但這是一個好點。如果存在全局的「Ad」,那麼它將被分配給'__index',這是更加意外的行爲。在玩metatables時應始終小心! – 2013-03-02 01:32:14

+0

謝謝你,這已經成功了。 – user1901873 2013-03-02 02:23:41