元表概念
Lua中,面向对向是用元表这种机制来实现的。元表是个很“道家”的机制,很深遂,很强大,里面有一些基本概念比较难理解透彻。不过,只有完全理解了元表,才能对Lua的面向对象使用自如,才能在写Lua代码的高级语法时游刃有余。
首先,一般来说,一个表和它的元表是不同的个体(不属于同一个表),在创建新的table时,不会自动创建元表。
但是,任何表都可以有元表(这种能力是存在的)。
e.g.
t = {}
print(getmetatable(t)) --> nil
t1 = {}
setmetatable(t, t1)
assert(getmetatable(t) == t1)
setmetatable( 表1, 表2) 将表2挂接为表1的元表,并且返回经过挂接后的表1。
元表中的__metatable字段,用于隐藏和保护元表。当一个表与一个赋值了__metatable的元表进行挂接时,用getmetatable操作这个表,就会返回__metatable这个字段的值,而不是元表!用setmetatable操作这个表(即给这个表赋予新的元表),那么就会引发一个错误。
table: 0x9197200
Not your business
lua: metatest.lua:12: cannot change a protected metatable
stack traceback:
[C]: in function 'setmetatable'
metatest.lua:12: in main chunk
[C]: ?
__index方法
元表中的__index元方法,是一个非常强力的元方法,它为回溯查询(读取)提供了支持。而面向对象的实现基于回溯查找。
当访问一个table中不存在的字段时,得到的结果为nil。这是对的,但并非完全正确。实际上,如果这个表有元表的话,这种访问会促使Lua去查找元表中的__index元方法。如果没有这个元方法,那么访问结果就为nil。否则,就由这个元方法来提供最终的结果。
__index可以被赋值为一个函数,也可以是一个表。是函数的时候,就调用这个函数,传入参数(参数是什么后面再说),并返回若干值。是表的时候,就以相同的方式来重新访问这个表。(是表的时候,__index就相当于元字段了,概念上还是分清楚比较好,虽然在Lua里面一切都是值
Lua中,面向对向是用元表这种机制来实现的。元表是个很“道家”的机制,很深遂,很强大,里面有一些基本概念比较难理解透彻。不过,只有完全理解了元表,才能对Lua的面向对象使用自如,才能在写Lua代码的高级语法时游刃有余。
首先,一般来说,一个表和它的元表是不同的个体(不属于同一个表),在创建新的table时,不会自动创建元表。
但是,任何表都可以有元表(这种能力是存在的)。
e.g.
t = {}
print(getmetatable(t)) --> nil
t1 = {}
setmetatable(t, t1)
assert(getmetatable(t) == t1)
setmetatable( 表1, 表2) 将表2挂接为表1的元表,并且返回经过挂接后的表1。
元表中的__metatable字段,用于隐藏和保护元表。当一个表与一个赋值了__metatable的元表进行挂接时,用getmetatable操作这个表,就会返回__metatable这个字段的值,而不是元表!用setmetatable操作这个表(即给这个表赋予新的元表),那么就会引发一个错误。
table: 0x9197200
Not your business
lua: metatest.lua:12: cannot change a protected metatable
stack traceback:
[C]: in function 'setmetatable'
metatest.lua:12: in main chunk
[C]: ?
__index方法
元表中的__index元方法,是一个非常强力的元方法,它为回溯查询(读取)提供了支持。而面向对象的实现基于回溯查找。
当访问一个table中不存在的字段时,得到的结果为nil。这是对的,但并非完全正确。实际上,如果这个表有元表的话,这种访问会促使Lua去查找元表中的__index元方法。如果没有这个元方法,那么访问结果就为nil。否则,就由这个元方法来提供最终的结果。
__index可以被赋值为一个函数,也可以是一个表。是函数的时候,就调用这个函数,传入参数(参数是什么后面再说),并返回若干值。是表的时候,就以相同的方式来重新访问这个表。(是表的时候,__index就相当于元字段了,概念上还是分清楚比较好,虽然在Lua里面一切都是值