programming in lua 初读18

本文介绍了Lua中的元表(metatables)和元方法(metamethods),包括它们如何改变table的行为,如自定义相加操作,以及如何通过元方法实现集合的并集和交集。还探讨了元表的共享、保护和监控表的概念,并举例说明了如何创建只读表。
摘要由CSDN通过智能技术生成

初学者,有错误希望指正。

18————————————Metatables and Metamethods
--lua中不可以对两个表执行操作,也不能比较大小
--metatables 允许我们改变table的行为
--以相加为例,local a={} b={} a+b 
--1 检查其中一个表是否带有metatale
--2 检查metatable是否有_add域
--3 如果有则调用_add函数
--[[
   有趣的一点
   任何一个表都可以是其他表的metatable,一组相关的表可以共享一个metatable(描述他们的共同行为)
   一个表也可以是自身的metatable(描述其私自行为)
]]
--使用getmetatable()获取metatable,默认创建的表是一个不带metatable的表
t={}
print(getmetatble(t))  -->nil
--s使用setmetatable函数设置或者改变一个表的meteatable
t1={}
setmetatable(t,t1)
print(getmetatable(t)) --> t1
————————————————————————
#!/usr/local/bin/lua
Set={}
function  Set.new(t)
   local set={}
   setmetatable(set,Set.mt)
   --创建表的同时指定对应的metatable,这样使用set.new创建的所有集合都有相同的metatabla
   for _,l in ipairs(t) do set[l]=true end
   return set
end
function Set.union(a,b)
    local res=Set.new{}
    for k in pairs(a) do res[k]=true end
    for k in pairs(b) do res[k]=true end
    return res
end
function Set.intersection(a,b)
    local res=Set.new{}
    for k in pairs(a) do
        res[k]=b[k]
    end
    return res
end
function Set.tostring(set)
    local s="{"
    local sep=""
    for e in pairs(set) do 
       s=s..sep..e
       sep=","
    end
    return s.."}"
end
function Set.print(s)
   print(Set.tostring(s))
end
function list_print(s)
  for k,v in pairs(s) do
      print(k,v)
  end
end
--定义一个普通的表作为metatale,避免污染命名空间,将其放在set内部
Set.mt={}
Set.mt.__add=Set.union
s1=Set.new{10,20,30,50}
s2=Set.new{30,34}
--print(getmetatable(s1))
--print(getmetatable(s2))
--给metatable增加__add函数
Set.mt.__add=Set.union
--[[
list_print(s1)
list_print(s2)
s3=s1+s2
list_print(s1)
list_print(s2)
list_print(s3)
print(type(s3))
Set.print(s3)
print(type(Set.tostring(s3)))
]]
Set.mt.__mul=Set.intersection
--可以通过设置不同的操作进行复杂操作,基础算术运算__add(加号),__mul(乘号),__sub(减号),__div(除号),__unm(负号)
--__pow(幂),这些只是表示符,真正代表操作的其实是=(等号)后的函数,并不一定就是与标识符名称一样的功能
--__concat : 定义连接行为
--  __ 这是双下划线,漏了话会报错attempt to perform arithmetic on a table value
Set,mt.__tostring=Set.tostring
--[[
  库定义 的metamethods
  metatable是一个普通的表,任何人都可以使用,可以在自己的metatables中定义自己的域
  以tostring为例。print总是调用tostring来格式化输出
  但是tostring会检查对象是否存在一个带有__tostring域调用自己定义的函数
输出
]]
Set.mt.__metatable="not your business"
print(getmetatable(s1))
setmetatable(s1,{})
--[[
   setmetatable/getmetatable 函数也会使用metafield.在这种情况下,可以保护metatables,
   通过对metatable设置了__metatable的值,getmetatale会返回这个值,setmetatable会出错
   保护集合的同时也使使用者既不能看到也不能修改metatablee
   输出
not your business
-/usr/local/bin/lua: ./metatable_test.lua:64: cannot change a protected metatable
]]
Set.print((s1+s2)*s1)
--[[
算术运算和关系运算的metamethods
————————————————————————————————————————————
以下摘自
http://manual.luaer.cn/2.8.html
"add": + 操作。
下面这个 getbinhandler 函数定义了 Lua 怎样选择一个处理器来作二元操作。 首先,Lua 尝试第一个操作数。 如果这个东西的类型没有定义这个操作的处理器,然后 Lua 会尝试第二个操作数。


     function getbinhandler (op1, op2, event)
       return metatable(op1)[event] or metatable(op2)[event]
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值