我能否覆盖Lua表的返回值?

当没有键引用时,是否可能让表返回特定值而不是返回自身的引用?

假设我有以下表:

local person = {
    name  = "Kapulani",
    level = 100,
    age   = 30,
}

在 Lua 中,我可以很容易地引用“person.name”、“person.level”或“person.age”,并按预期获得值。然而,我有某些情况,我可能只想引用“person”,而不是得到“table: ”,我想返回“person.name”的值。

换句话说,我想让 person.x(或 person[x])返回表中的适当条目,但没有键的 person 返回 person.name 的值(或 person["name"])。我没有能找到这种机制吗?

我尝试过使用元表,但没有成功,因为 __index 只适用于键不存在的情况。如果我将“person”放入一个单独的表中,我可以想出以下代码:

local true_person = {
    ... -- 如上
}

local env_mt = {
    __index = function(t, k)
        if k == 'person' then
            return true_person
        end
    end
}

local env = setmetatable( {}, env_mt )

这使我可以使用 __index 做一些特殊处理,但是我没有找到从 __index() 中分辨出我是想要 env.person(我想要返回 true_person.name)还是 env.person[key](我想要返回 true_person 作为一个表,以便可以适当地访问“key”)。

有什么想法吗?我可以用不同的方法来解决这个问题,但是希望能够以这样的方式解决。

点赞
用户258523
用户258523

当表被用作字符串时,可以通过设置__tostring元表条目来完成:

$ cat st.lua
local person = {
    name  = "Kapulani",
    level = 100,
    age   = 30,
}

print(person)
print(person.name)
print(person.age)

setmetatable(person, {__tostring = function(t) return t.name end})
print(person)

$ lua st.lua
lua st.lua
table: 0x1e8478e0
Kapulani
30
Kapulani
2014-07-17 21:07:34
用户90511
用户90511

我不确定你现在需要的东西是否是一个好方法,因为它违背了部分性的原则。通常情况下,以下两个程序会做相同的事情,但你希望它们的行为不同。

print(person.name)

local p = person
print( p.name )

同时,赋值的机制也不是很清晰。person.age = 10 会改变年龄,但是 person = otherPerson 应该会改变对 person 的引用,而不是年龄。

如果你不在意部分性,仅仅是在读取数据,那么有一个更直接的方式解决这个问题:拥有一个通过字符串编码的字段的查询函数。

query("person.age")   -- 17
query("person.name")  -- "hugomg"
query("person")       -- 17;query 可以选择活得默认结果。

为了让语法更加简洁,你可以省略可选的 parenthesis

q"person.age"
q"person"

或者你可以扩展全局表_G__index 元方法:

setmetattable(_G, { __index = function(self, key) return query(key) end })

print ( person_age )  --你需要用“_”而不是“.”来代替查询作为有效标识符。
2014-07-18 05:31:19