Lua学习笔记之元表元方法

来源:互联网 发布:淘宝衣服直播主播招聘 编辑:程序博客网 时间:2024/06/03 13:41
“环境” setfenv getfenv
我们任何变量的值都是在堆上保存着,我们的变量名只是这个变量值的引用,这些引用或许是有一个引用的作用域链在维护管理它们的使用范围,
一,元表
  table 和 userdata可以有各自独立的元表。其他类型默认情况下没有元表。
  可以通过元表来修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定的操作。
  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 )


四,组合使用__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个方法里面任何操作,随意了。
0 0
原创粉丝点击