zoukankan      html  css  js  c++  java
  • Lua中实现类似C#的事件机制

    Lua的语法非常灵活, 使用他的metatable及metamethod可以模拟出很多语言的特性.

    C#中我们这样使用事件:

    xxx.Click += new System.EventHandler(xxx_Click);
    private void xxx_Click(object sender, EventArgs e)
    {
    /**/
    }
    

    在Lua中要达到同样的效果, 并且支持事件多播机制, 其关键在于重写metamethod __call, 从而使得不光function才能被调用, table也能够被调用.

    主要思想就是, 通过一个table来保存注册事件的若干响应函数, 然后拿table当function一样来调用, 重写__call后, 实现调用table时遍历执行table中的注册方法.

    需要在lua5.0 或 lua.net上执行, lua 5.1略有改动.

    1 --test.lua
       2 do
       3
       4 --事件原型对象, 所有事件由此原型生成
       5 Event = {}
       6
       7 function Event:New()
       8         local event = {}
       9         setmetatable(event, self)
      10         --覆盖__index逻辑
      11         self.__index = self
      12         --覆盖__call逻辑
      13         self.__call = self.Call
      14         return event
      15 end
      16
      17 --事件注册, 通过此方法将响应方法注册到事件上.
      18 --@source:响应方法的所属对象
      19 --@func:响应方法
      20 function Event:Add(source, func)
      21         table.insert(self, {source, func})     
      22 end
      23
      24 --内部方法, 重写了默认__call逻辑, 当event被触发调用时, 循环执行event中注册的响应方法
      25 --@table:对象产生调用时将本身传入
      26 --@...:调用参数
      27 function Event.Call(table, ...)
      28         for _, item in ipairs(table) do
      29                 --item[1]就是source, item[2]就是func响应方法
      30                 --lua 5.1中无需使用unpack(arg), 直接使用...即可
      31                 item[2](item[1], unpack(arg))
      32         end
      33 end
      34
      35 ------------------以下为测试用例-----------------------
      36
      37 --创建一个window对象, 注册按钮的点击事件
      38 Window = {
      39         Name = "Simonw's Window",      
      40 }
      41
      42 function Window:Init()
      43         --注册事件, self即Window, 对象来源.
      44         Button.ClickEvent:Add(self, self.Button_OnClick)       
      45 end
      46
      47 --响应事件方法, sender即是传来的Button对象
      48 function Window:Button_OnClick(sender) 
      49         print(sender.Name.." Click On "..self.Name)
      50 end
      51
      52 --创建一个button对象, 拥有ClickEvent这样的事件
      53 Button = {
      54         Name = "A Button",
      55         --创建事件
      56         ClickEvent = Event:New(),
      57 }
      58
      59 --执行点击按钮的动作
      60 function Button:Click()
      61         print('Click begin')
      62         --触发事件, self即sender参数
      63         self.ClickEvent(self)
      64         print('Click end')
      65 end
      66
      67 --从这里执行
      68 Window:Init()
      69 Button:Click()
      70 --[[
      71 执行结果:
      72 > dofile 'test.lua'
      73 Click begin
      74 A Button Click On Simonw's Window
      75 Click end
      76 ]]
      77
      78 end

    
    
  • 相关阅读:
    【VirtualBox】共享文件夹失效问题
    【Ubuntu】全局代理
    phpStudy(lnmp)集成环境安装
    MemcacheQ 的安装与使用
    Windows 64位下安装Redis详细教程
    http与https的区别
    cookie 和session 的区别详解
    setcookie各个参数详解
    MySQL 数据备份与还原
    linux命令行下导出导入.sql文件
  • 原文地址:https://www.cnblogs.com/flying_bat/p/921080.html
Copyright © 2011-2022 走看看