当我们访问一个表的不存在的域,返回结果为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章详细的讨论继承的方式。
Lua,__index方法
更新日志
- 【原神手游】5.1版本更新维护预告
- 李锦华.1987-日与夜(LP版)【SOLO】【WAV+CUE】
- 伍珂玥.2014-伍珂玥【湾彩星辰】【FLAC分轨】
- 吕方.2001-旧情人·老情歌精选2CD【华纳】【WAV+CUE】
- 《星际战士2》¥219,《100% 鲜橙汁》¥7
- 手办鉴赏室:少女眼神颇有杀意!连衣裙勾勒傲人轮廓
- 未来可期的二次元大逃杀游戏——《白厄战境》简评
- 炉石传说死亡骑士卡组怎么搭配 死亡骑士最新卡组2024推荐
- 魔兽世界地下堡珍玩怎么升级 地下堡珍玩升级方法攻略分享
- 魔兽世界怎么获得泽克维尔的残血珍玩 泽克维尔的残血珍玩获取方式
- FrankSinatra-StrangersInTheNight(1966Jazz)[Flac24-96]
- 大原樱子《CAMON+5thAnniversaryBest~》2CD[24-96]flac
- Isgaard2003-GoldenKey(LimitedEdition)【WAV+CUE】
- 《合金装备3RE》伊娃定妆照公布:没被政确太好了
- 石家庄新增《黑神话:悟空》墙绘:小狐狸萍萍