__index 元方法

简介: __index 元方法

正如我们之前所看到的,当访问一个表中不存在的字段时会得到 nil 。这是正确的,但不是完整的真相。实际上,这些访问会引发解释器查找一个名为 __index 的元方法。如果没有这个元方法,那么像一般情况下一样,结果就是 nil ;否则,则由这个元方法来提供最终结果。


下面介绍一个关于继承的原型示例。假设我们要创建几个表来描述窗口,每个表中必须描述窗口的一些参数,例如位置、大小及主题颜色等。所有的这些参数都有默认值,因此我们希望在创建窗口对象时只需要给出那些不同于默认值的参数即可。第一种方法是使用一个构造器来填充不存在的字段,第二种方法是让新窗口从一个原型窗口继承所有不存在的字段。首先,我们声明一个原型:

-- 创建具有默认值的原型
prototype = {x = 0, y = 0, width = 100, height = 100}


然后,声明一个构造函数,让构造函数创建共享同一个元表的新窗口:

local mt = {}     -- 创建一个元表
-- 声明构造函数
function new (o)
  setmetatable(o, mt)
  return o
end


现在,我们来定义元方法 __index

mt.__index = function (_, key)
  return prototype[key]
end


在这段代码后,创建一个新窗口,并查询一个创建时没有指定的字段:

w = new{x = 10, y = 20}
print(w.width)    --> 100


Lua 语言会发现 w 中没有对应的字段 "width" ,但却有一个带有 __index 元方法的元表。因此, Lua 语言会以 w (表)和 "width" (不存在的键)为参数来调用这个元方法。元方法随后会用这个键来检索原型并返回结果。


Lua 语言中,使用元方法 __index 来实现继承是很普遍的方法。虽然被叫做方法,但元方法 __index 不一定必须是一个函数,它还可以是一个表。当元方法是一个函数时, Lua 语言会以表和不存在的键为参数调用该函数,正如我们刚刚看到的。当元方法是一个表时, Lua 语言就访问这个表。因此,在我们此前的示例中,可以把 __index 简单地声明为如下样式:

mt.__index = prototype


这样,当 Lua 语言查找元表的 __index 字段时,会发现字段的值是表 prototype 。因此, Lua 语言就会在这个表中继续查找,即等价地执行 prototype["width"] ,并得到预期的结果。


将一个表用作 __index 元方法为实现带继承提供了一种简单快捷的方法。虽然将函数用作元方法开销更昂贵,但函数却更加灵活:我们可以通过函数来实现多继承缓存及其他一些变体。


如果我们希望在访问一个表时不调用 __index 元方法,那么可以使用函数 rawget 。调用 rawget(t, i) 会对表 t 进行原始的访问,即在不考虑元表的情况下对表进行简单的访问。进行一次原始访问并不会加快代码执行(一次函数调用的开销就会抹杀用户所做的这些努力),但是,我们后续会看到,有时确实会用到原始访问。

目录
相关文章
|
5月前
Element UI 【表格合计】el-table 实战范例 -- 添加单位,自定义计算逻辑
Element UI 【表格合计】el-table 实战范例 -- 添加单位,自定义计算逻辑
431 0
|
存储 机器学习/深度学习 安全
C++模板元模板实战书籍讲解第一章(元函数与type_traits)
C++模板元模板实战书籍讲解第一章(元函数与type_traits)
107 0
|
开发者
element el-table固定列凹陷问题
element el-table固定列凹陷问题
114 0
库定义相关的元方法
库定义相关的元方法
43 0
元表和元方法
元表和元方法
60 0
|
PHP
TP5.1隐藏public/index.php第二种方式
TP5.1隐藏public/index.php第二种方式
172 0
TP5.1隐藏public/index.php第二种方式
|
前端开发 开发者
z-index 属性 | 学习笔记
快速学习 z-index 属性。
118 0
|
Web App开发 JavaScript
深入理解z-index
要解决的问题 在页面编写的过程中,经常需要处理元素的重叠。重叠的顺序不当则容易造成元素被错误地遮盖等现象。一般地,有很多人认为只需要指定元素的z-index即可调整重叠的顺序,但是实际上并不是这样的。
1548 0
z-index无效解决
1、父标签 position属性为relative; 2、问题标签无position属性(不包括static); 3、问题标签含有浮动(float)属性。
1587 0