Lua学习笔记之元表元方法
元表
table
和 userdata
可以有各自独立的元表。Lua中,每个值都有一个元表, 其他类型的值则共享其类型所属的单一元表。
可以通过元表来修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定的操作。
setmetatable( t , t1 ) 设置t的元表 为t1
assert( getmetatable( t ) == t1 )
print( getmetatable( “hi”) ) -->table:xxxxxxx
print( getmetatable(10) ) -->nil
local mt = {}
........in Set.new..........
.........
setmetatable( set , mt )
...........
元方法:
(存在于元表里面的特殊方法,一般以__开头)
将元方法加入元表
mt.__add = Set.union
这样就可以直接调用:
s3 = s1 + s2
每一种算数操作符都有对应的字段名:
__add ==> ‘ + ’ __mul ==> ‘ * ’ __sub ==> ‘ - ’ __div ==> ‘ / ’
__unm 相反数 __mod ==> ’ % ’ __pow(乘幂) __concat(连接操作)
关系类对应元方法:
__eq(等于) __lt(小于) __le(小于等于)
函数getmetatable 和 setmetatable也会用到元表中的一个字段,用于保护元表。__metatable。使用户不能看到,不能修改元表,更何况元表里面的元方法。
mt.__metatable = “not your business”
s1 = Set.new{ }
getmetatable( s1 ) --> ‘not your business’
setmetatable( s1 , { } ) --> stdin:1 cannot change protected metatable
table自己访问的元方法
Lua提供一种可以改变table行为的方法。有2种可以改变的table行为:查询table中不存在的字段 , 修改table中不存在的字段
__index : 当访问一个table中不存在的字段时,lua会检查是否有__index的元方法。没有它,返回nil,有它,返回这个方法提供的结果。
__index 有2种实现体:function , table
Window.prototype = { x = 0 , y = 0 , width = 200 , height = 200 }
Window.mt = { }
--第一种:(通过这种方式,可以实现多继承,缓存等功能)
Window.mt.__index = function( table , key )
return Window.prototype[key]
end
--第二种:(便捷继承查表方式)
Window.mt._index = Window.prototype
**__newindex: ** 用于table的更新。
当对一个table中不存在的索引赋值的时候,解释器就会查找__newindex元方法。与__index一样,__newindex是个function的话,调用之;__newindex是个table,就在这个table中添加k,v,而不是原来的table
rawset( t , k , v ) 和 rawget( t , i ) --2个函数
组合使用__index和__newindex:
具有默认值的table:通过使用__index元方法。
只读的table:
function readOnly( t )
local proxy = { }
local mt = {
__index = t,
__newindex = function( t , k , v )
error(“attempt to update a read-only table” , 2 )
end
}
setmetatable( proxy , mt )
return proxy
end
-- 创建一个table,然后调用readOnly函数就会使这个table只读。
总结: __index和__newindex应用在查询,修改table中不存在的字段。那么,构造一个proxy是空表,自然什么都是不存在的字段,所以,来自调用者的任何查询和修改都是基于不存在的字段,自然都会找到__index和__newindex的方法,继而,调用之,在这2个方法里面任何操作,随意了。