事件声明

时间:2012-11-23 21:59:14

标签: ruby

我今天从@ avdi的Ruby Tapas剧集中获得了以下代码:

module Eventful
  def self.included(other)
    other.extend(Macros)
  end
  def add_listener(listener)
    (@listeners ||= []) << listener
  end
  def notify_listeners(event, *args)
    (@listeners || []).each do |listener|
      listener.public_send("on_#{event}", *args)
    end
  end

  module Macros
    def event(name)
      module_eval(%Q{
        def #{name}(*args)
          notify_listeners(:#{name}, *args)
        end
      })
    end
  end
end

class Dradis
  include Eventful
  event :new_contact
end

class ConsoleListener
  def on_new_contact(direction, range)
    puts "DRADIS contact! #{range} kilometers, bearing #{direction}"
  end
end

dradis = Dradis.new
dradis.add_listener(ConsoleListener.new)
dradis.new_contact(120, 23000)

我理解事件和侦听器的概念以及观察者模式,但是不了解这种语法是如何工作的原因,也没有在任何手册中看到它。班级Dradis有:

 event :new_contact

首先,我认为event是一种方法,而:new_contact是一个参数,因此我会在event的实例上调用Dradis,例如:< / p>

dradis = Dradis.new
dradis.event

但是,在new_contact的实例上调用Dradis,如:

dradis = Dradis.new
dradis.add_listener(ConsoleListener.new)
dradis.new_contact(120, 23000)

并触发宏模块中的event方法。

任何人都可以解释为什么它会这样吗?在实例:new_contact上调用dradis来触发事件方法?

2 个答案:

答案 0 :(得分:1)

我没看过这一集,但看,它就在那里。

  module Macros
    def event(name)
      module_eval(%Q{
        def #{name}(*args)
          notify_listeners(:#{name}, *args)
        end
      })
    end
  end

event是一种定义另一种方法(new_contact)的方法,该方法从notify_listeners调用Eventful

  

并触发宏模块中的事件方法

不正确的。该方法很久以前就完成了它的工作,并且不再被调用。它使用module_eval / def生成了一种新方法,并且新方法(new_contact)正在被调用。

重要的是要理解event方法仅在解析和加载Dradis类时运行一次。它不会在Dradis的每个实例化上运行。

答案 1 :(得分:1)

使用了ruby的几个独立功能:在行event :new_contact中,“evnet”是类方法(http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_classes.html#UE )。

通常类方法由:

定义
  class A
    def A.my_class_method
     #code
    end
  end
  A.my_class_method #executing class_method

  class A
    def <<self   #usefull when you want delare several class methods
      def A.my_class_method
        #code
      end
    end
  end
  A.my_class_method #executing class_method

在代码中,方法包含在模块Macros中。

关键是,(类方法)event动态创建新的(实例)方法(在本例中为new_contact) 方法的名称作为参数传递给event)。并且这种方法提供了对侦听器的调用。

  

任何人都可以解释为什么它会这样吗?在实例dradis上调用:new_contact来触发事件方法?

这是通过动态创建的方法new_contact来调用notify_listeners(:#{name}, *args)