2013-03-01 140 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