表相关的元方法(Metamethods)The __index Metamethod
Posted 森明帮大于黑虎帮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了表相关的元方法(Metamethods)The __index Metamethod相关的知识,希望对你有一定的参考价值。
关于算术运算和关系元运算的 metamethods
都定义了错误状态的行为,他们并不改变语言本身的行为。针对在两种正常状态:表的不存在的域的查询和修改, Lua 也提供了改变 tables 的行为的方法。
前面说过,当我们访问一个表的不存在的域,返回结果为 nil
,这是正确的,但并不一定正确。实际上,这种访问触发 lua
解释器去查找__index metamethod
:如果不存在,返回结果为 nil
;如果存在则由__index metamethod
返回结果。
这个例子的原型是一种继承。假设我们想创建一些表来描述窗口。每一个表必须描述窗口的一些参数, 比如:位置,大小,颜色风格等等。所有的这些参数都有默认的值,当我们想要创建窗口的时候只需要给出非默认值的参数即可创建我们需要的窗口。第一
种方法是,实现一个表的构造器,对这个表内的每一个缺少域都填上默认值。第二种方法是,创建一个新的窗口去继承一个原型窗口的缺少域。首先,我们实现一个原型和一个构造函数,他们共享一个 metatable
:
现在我们定义__index metamethod
:
这样一来,我们创建一个新的窗口,然后访问他缺少的域结果如下:
当 Lua
发现 w
不存在域 width
时,但是有一个 metatable
带有__index
域, Lua
使用w(the table)和 width(缺少的值)
来调用__index metamethod
, metamethod
则通过访问原型表(prototype)
获取缺少的域的结果。
__index metamethod
在继承中的使用非常常见,所以 Lua
提供了一个更简洁的使用方式。 __index metamethod
不需要非是一个函数,他也可以是一个表。但它是一个函数的时候, Lua 将 table 和缺少的域作为参数调用这个函数;当他是一个表的时候, Lua 将在这个表中看是否有缺少的域。所以,上面的那个例子可以使用第二种方式简单的改写为:
现在,当 Lua
查找 metatable
的__index
域时,他发现 window.prototype
的值,它是一个表,所以 Lua
将访问这个表来获取缺少的值,也就是说它相当于执行:
将一个表作为__index metamethod
使用,提供了一种廉价而简单的实现单继承的方法。一个函数的代价虽然稍微高点,但提供了更多的灵活性:我们可以实现多继承,隐藏,和其他一些变异的机制。我们将在后续详细的讨论继承的方式。
当我们想不通过调用__index metamethod
来访问一个表,我们可以使用 rawget
函数。Rawget(t,i)
的调用以 raw access
方式访问表。这种访问方式不会使你的代码变快( theoverhead of a function call kills any gain you could have),但有些时候我们需要他,在后面我们将会看到。
以上是关于表相关的元方法(Metamethods)The __index Metamethod的主要内容,如果未能解决你的问题,请参考以下文章
Lua_第 12 章 Metatables and Metamethods