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  阅读(175)  评论(0编辑  收藏  举报