3

对于深度嵌套表中的字段,例如 text.title.1.font。即使你使用

if text.title.1.font then ... end

如果表的任何级别实际上不存在,它将导致类似“尝试索引全局'文本'(零值)”的错误。当然,可能会尝试检查表的每一级是否存在,但这似乎相当麻烦。我想知道是否有一种安全且更漂亮的方法来处理这个问题,这样当引用这样的对象时,nil 将是值而不是触发错误?

4

2 回答 2

1

Egor 的建议debug.setmetatable(nil, {__index = function()end})是最容易应用的。请记住,它不是词法范围的,因此,一旦打开,它将一直处于“打开”状态,直到关闭,这可能会对代码的其他部分产生意想不到的后果。有关讨论和一些替代方案,请参见此线程

还要注意text.title.1.font应该是text.title[1].fontor text.title['1'].font(而且这两个不一样)。

另一个更冗长但仍然可用的替代方法是:

if (((text or {}).title or {})[1] or {}).font then ... end
于 2014-05-21T16:30:29.797 回答
1

这样做不会引起很多错误的方法是明确告诉 Lua 哪些表的哪些字段默认应该是表。您可以使用元表来做到这一点。以下是一个示例,但实际上应该根据您希望表格的结构对其进行自定义。

-- This metatable is intended to catch bugs by keeping default tables empty.
local default_mt = {
  __newindex =
    function()
      error(
    'This is a default table. You have to make nested tables the old-fashioned way.')
    end
}

local number_mt = {
  __index =
    function(self, key)
      if type(key) == 'number' then
    return setmetatable({}, default_mt)
      end
    end
}

local default_number_mt = {
  __index = number_mt.__index,
  __newindex = default_mt.__newindex
}

local title_mt = {__index = {title = setmetatable({}, default_number_mt)}}

local text = setmetatable({}, title_mt)

print(text.title[1].font)
于 2014-05-21T17:59:45.210 回答