如何简单易懂的理解lua的元表metatable
3个回答
展开全部
Lua 的 metatable 并不只是为了 OO 而存在,但 Lua 的面向对象机理,prototype based object orientation,的确是通过 metatable 而实现的。
简单来说,prototype based OO 的根本特征是不采用「类」这一层抽象,也就是说,所有对象都是没有 class 的 instance。当一个 object 需要某个其他 object 已有的功能时,可以将后者设为自己的 prototype;同一个 object 可以同时作为几个其他 object 共同的 prototype(但反之通常不成立);已指定 prototype 的 object 还可以成为其他 object 的 prototype;一个 object 可以以自己为 prototype。一系列 object 以此方式组成一串 prototype 链,在某个 object 上调用它并未定义的方法或属性时,系统会上溯这条链,依次查看每一级 prototype 是否有定义,直至找到或穷尽到链条终点为止。举例而言,假设有三个维京人,甲会弹弓,乙会用剑,丙会持盾牌;甲给乙当 prototype,于是乙也会了弹弓;乙再给丙当 prototype,丙就成了可以持盾挥剑射弹弓的全能维京人。甲没有 prototype(或者有一个什么都不会的缺省 prototype),丙则不是任何人的 prototype(但他可以是)。
具体到 Lua 这里,这种「向上寻找 prototype」的机制,可以用 metatable 之中的 metamethod 完成。最简单但并不是最简洁的例子:
a = { foo = function() return 'foo' end }
b = { bar = function() return 'bar' end }
c = { __index = b }
setmetatable(a, c)
a.bar()
-- 'bar'
将 table c 的 __index 定义为 table b,然后将 a 的 metatable 定为 c,就让 b 变成了 a 的 prototype。而 c 作为 metatable 的角色其实可以融合到 b 或者 a 中:
a = { foo = function() return 'foo' end }
b = { bar = function() return 'bar' end }
b.__index = b
setmetatable(a, b)
a.bar()
-- 'bar'
这样一来,b 既是 a 的 prototype,也是 a 的 metatable。将 __index 指向另一个 table 大概是它最简单也最普遍的用法,只是 Lua 官方教程中引入 __index 的部分写得比较复杂,把它写成了一个函数,意图大概是考虑到大部分读者对 prototype based OO 并不是很了解(那时候 JavaScript 还没有现在这么流行),所以用 metatable 来强行实现了一个看起来很接近 class-based 的 OO。
简单来说,prototype based OO 的根本特征是不采用「类」这一层抽象,也就是说,所有对象都是没有 class 的 instance。当一个 object 需要某个其他 object 已有的功能时,可以将后者设为自己的 prototype;同一个 object 可以同时作为几个其他 object 共同的 prototype(但反之通常不成立);已指定 prototype 的 object 还可以成为其他 object 的 prototype;一个 object 可以以自己为 prototype。一系列 object 以此方式组成一串 prototype 链,在某个 object 上调用它并未定义的方法或属性时,系统会上溯这条链,依次查看每一级 prototype 是否有定义,直至找到或穷尽到链条终点为止。举例而言,假设有三个维京人,甲会弹弓,乙会用剑,丙会持盾牌;甲给乙当 prototype,于是乙也会了弹弓;乙再给丙当 prototype,丙就成了可以持盾挥剑射弹弓的全能维京人。甲没有 prototype(或者有一个什么都不会的缺省 prototype),丙则不是任何人的 prototype(但他可以是)。
具体到 Lua 这里,这种「向上寻找 prototype」的机制,可以用 metatable 之中的 metamethod 完成。最简单但并不是最简洁的例子:
a = { foo = function() return 'foo' end }
b = { bar = function() return 'bar' end }
c = { __index = b }
setmetatable(a, c)
a.bar()
-- 'bar'
将 table c 的 __index 定义为 table b,然后将 a 的 metatable 定为 c,就让 b 变成了 a 的 prototype。而 c 作为 metatable 的角色其实可以融合到 b 或者 a 中:
a = { foo = function() return 'foo' end }
b = { bar = function() return 'bar' end }
b.__index = b
setmetatable(a, b)
a.bar()
-- 'bar'
这样一来,b 既是 a 的 prototype,也是 a 的 metatable。将 __index 指向另一个 table 大概是它最简单也最普遍的用法,只是 Lua 官方教程中引入 __index 的部分写得比较复杂,把它写成了一个函数,意图大概是考虑到大部分读者对 prototype based OO 并不是很了解(那时候 JavaScript 还没有现在这么流行),所以用 metatable 来强行实现了一个看起来很接近 class-based 的 OO。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
2、老罗拉了一车梨,
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
2017-10-11
展开全部
八、让中、英文输入法智能化地出现
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询