Lua中的__index方法详解
程序员文章站
2022-04-09 22:57:58
当我们访问一个表的不存在的域,返回结果为nil,这是正确的,但并不一定正确。实际上,这种访问触发lua解释器去查找__index metamethod:如果不存在,返回结果...
当我们访问一个表的不存在的域,返回结果为nil,这是正确的,但并不一定正确。实际上,这种访问触发lua解释器去查找__index metamethod:如果不存在,返回结果为nil;如果存在则由__index metamethod返回结果。
这个例子的原型是一种继承。假设我们想创建一些表来描述窗口。每一个表必须描述窗口的一些参数,比如:位置,大小,颜色风格等等。所有的这些参数都有默认的值,当我们想要创建窗口的时候只需要给出非默认值的参数即可创建我们需要的窗口。第一种方法是,实现一个表的构造器,对这个表内的每一个缺少域都填上默认值。第二种方法是,创建一个新的窗口去继承一个原型窗口的缺少域。首先,我们实现一个原型和一个构造函数,他们共享一个metatable:
复制代码 代码如下:
-- 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 metamethod:
复制代码 代码如下:
window.mt.__index = function (table, key)
return window.prototype[key]
end
这样一来,我们创建一个新的窗口,然后访问他缺少的域结果如下:
复制代码 代码如下:
w = window.new{x=10, y=20}
print(w.width) --> 100
当lua发现w不存在域width时,但是有一个metatable带有__index域,lua使用w(the table)和width(缺少的值)来调用__index metamethod,metamethod则通过访问原型表(prototype)获取缺少的域的结果。
__index metamethod在继承中的使用非常常见,所以lua提供了一个更简洁的使用方式。__index metamethod不需要非是一个函数,他也可以是一个表。但它是一个函数的时候,lua将table和缺少的域作为参数调用这个函数;当他是一个表的时候,lua将在这个表中看是否有缺少的域。所以,上面的那个例子可以使用第二种方式简单的改写为:
复制代码 代码如下:
window.mt.__index = window.prototype
现在,当lua查找metatable的__index域时,他发现window.prototype的值,它是一个表,所以lua将访问这个表来获取缺少的值,也就是说它相当于执行:
复制代码 代码如下:
window.prototype["width"]
将一个表作为__index metamethod使用,提供了一种廉价而简单的实现单继承的方法。一个函数的代价虽然稍微高点,但提供了更多的灵活性:我们可以实现多继承,隐藏,和其他一些变异的机制。我们将在第16章详细的讨论继承的方式。
上一篇: C调用lua函数需要考虑的问题
下一篇: Lua返回一个Closures函数实例
推荐阅读
-
Symfony2实现在controller中获取url的方法_php实例
-
Yii中CGridView关联表搜索排序方法实例详解,yiicgridview_PHP教程
-
Bootstrap模态对话框中显示动态内容的方法
-
PHP array_key_exists检查键名或索引是否存在于数组中的实现方法_php实例
-
watch在Vue.js中的使用方法详解
-
PHP中实现生成静态文件的方法缓解服务器压力_PHP
-
SQL中Exists的用法实例详解
-
mysql中sum float类型使用小数点的方法_MySQL
-
php中判断数组是一维,二维,还是多维的解决方法_php实例
-
探讨fckeditor在Php中的配置详解_php技巧