我今天从@ 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
来触发事件方法?
答案 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)