Lua学习笔记之元表元方法

元表

tableuserdata可以有各自独立的元表。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个方法里面任何操作,随意了。

posted @ 2014-08-09 23:26  Appleegig  阅读(212)  评论(0)    收藏  举报