第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些区别。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目


13.3 – 库定义的元方法

一些库定义元表中的自己的字段是一种常见做法。到目前为止,我们看到的所有元方法都属于 Lua 核心。虚拟机检测到操作中涉及的值具有元表,并且这些元表为该操作定义了元方法。但是,由于元表是常规表,因此任何人都可以使用它。

tostring 函数提供了一个典型的示例。如前所述,tostring 以相当简单的格式表示表

    print({})      --> table: 0x8062ac0
(请注意,print 始终调用 tostring 来格式化其输出。)但是,在格式化对象时,tostring 首先检查对象是否具有带有 __tostring 字段的元表。如果是这种情况,tostring 调用相应的值(必须是函数)来完成其工作,并将对象作为参数传递。此元方法返回的任何内容都是 tostring 的结果。

在我们使用集合的示例中,我们已经定义了一个函数将集合表示为字符串。因此,我们只需要在集合元表中设置 __tostring 字段

    Set.mt.__tostring = Set.tostring
在那之后,每当我们使用集合作为其参数调用 print 时,print 调用 tostring,而 tostring 调用 Set.tostring
    s1 = Set.new{10, 4, 5}
    print(s1)    --> {4, 5, 10}

setmetatable/getmetatable 函数也使用元字段,在这种情况下用于保护元表。假设您想保护您的集合,以便用户既看不到也无法更改它们的元表。如果您在元表中设置 __metatable 字段,getmetatable 将返回此字段的值,而 setmetatable 将引发错误

    Set.mt.__metatable = "not your business"
    
    s1 = Set.new{}
    print(getmetatable(s1))     --> not your business
    setmetatable(s1, {})
      stdin:1: cannot change protected metatable