第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些区别。
第四版针对 Lua 5.3,可在 Amazon 和其他书店购买。
购买本书,您还可以帮助 支持 Lua 项目。
用 Lua 编程 | ||
第二部分。表和对象 第 13 章。元表和元方法 |
__index
元方法我之前说过,当我们访问表中不存在的字段时,结果是 nil。这是真的,但并不是全部。实际上,这种访问会触发解释器查找 __index
元方法:如果没有这种方法(通常如此),则访问结果为 nil;否则,元方法将提供结果。
这里的典型示例是继承。假设我们要创建几个描述窗口的表。每个表都必须描述几个窗口参数,例如位置、大小、配色方案等。所有这些参数都有默认值,因此我们希望仅给出非默认参数来构建窗口对象。第一个备选方案是提供一个填充不存在字段的构造函数。第二个备选方案是安排新窗口从原型窗口继承任何不存在的字段。首先,我们声明原型和构造函数,它创建共享元表的窗口
-- create a namespace Window = {} -- create the prototype with default values Window.prototype = {x=0, y=0, width=100, height=100, } -- create a metatable Window.mt = {} -- declare the constructor function function Window.new (o) setmetatable(o, Window.mt) return o end现在,我们定义
__index
元方法
Window.mt.__index = function (table, key) return Window.prototype[key] end在该代码之后,我们创建一个新窗口并查询不存在的字段
w = Window.new{x=10, y=20} print(w.width) --> 100当 Lua 检测到
w
没有请求的字段,但有一个具有 __index
字段的元表时,Lua 会调用此 __index
元方法,参数为 w
(表)和 "width"
(不存在的键)。然后,元方法使用给定的键对原型进行索引并返回结果。
__index
元方法用于继承非常常见,因此 Lua 提供了一个快捷方式。尽管名称为 __index
,但元方法不必是函数:它可以是表。当它是一个函数时,Lua 会使用表和不存在的键作为其参数来调用它。当它是一个表时,Lua 会在该表中重新进行访问。因此,在我们的前一个示例中,我们可以简单地将 __index
声明为
Window.mt.__index = Window.prototype现在,当 Lua 查找元表的
__index
字段时,它会找到 Window.prototype
的值,它是一个表。因此,Lua 会在此表中重复访问,即执行等效于
Window.prototype["width"]这会给出所需的结果。
将表用作 __index
元方法提供了一种实现单一继承的廉价且简单的方法。函数虽然开销更大,但提供了更大的灵活性:我们可以实现多重继承、缓存和许多其他变体。我们将在 第 16 章 中讨论这些继承形式。
当我们想要访问表而不调用其 __index
元方法时,我们使用 rawget
函数。调用 rawget(t,i)
对表 t
执行原始访问。执行原始访问不会加快代码速度(函数调用的开销会抵消任何收益),但有时您需要它,正如我们稍后将看到的。
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |