2012-11-23 2 views
0

나는 오늘 @ avdi의 루비 타파스 에피소드에서 다음 코드를 가지고 : 나는 이벤트와 청취자와 관찰자 패턴의 개념을 이해이벤트 선언

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 = Dradis.new 
dradis.event 

:

event :new_contact 

는 처음에 나는 event이 방법이었고, 나는, Dradis의 인스턴스에 뭔가를 event를 호출 할 수 있도록 :new_contact 인수이라고 생각 : 클래스 Dradis이가있다 대신, new_contactDradis의 인스턴스에서 호출 같은 :

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

그 매크로 모듈에서 event 메서드를 트리거합니다.

아무도 왜 이렇게 작동하는지 설명 할 수 있습니까? 인스턴스 dradis:new_contact을 호출하면 이벤트 메소드가 트리거됩니까?

답변

1

나는 에피소드를 보지 못했지만, 본다.

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

eventEventful

notify_listeners에서 호출하는 다른 방법 ( new_contact)를 정의하는 방법이다.

그것은

잘못된 매크로 모듈에서 이벤트 방법을 트리거한다. 이 방법은 오래 전에 작업을 마쳤으며 다시 호출되지 않습니다. module_eval/def을 사용하여 새로운 방법을 만들었으며 새로운 방법 (new_contact)이 호출되었습니다.

event 메서드는 Dradis 클래스가 구문 분석되어로드 될 때 한 번만 실행된다는 점을 이해해야합니다. Dradis의 모든 인스턴스에서 실행되지 않습니다.

+0

감사를 호출하는 dynammically 생성 방법 new_contact입니다? 어떻게 이벤트가 호출됩니까? – BrainLikeADullPencil

+0

아니요, Dradis 클래스가 구문 분석되어로드 될 때 호출됩니다. –

1

루비의 여러 분리 된 기능이 사용됩니다. 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는 dynamicaly 메소드의 이름이 event에 인수로 전달됩니다) (이 경우 new_contact에서) 새 (예) 메소드를 만드는 것입니다. 그리고이 방법은 청취자에게 전화를 제공합니다.

왜 이런 식으로 작동하는지 설명 할 수 있습니까? 호출 : 이벤트 메소드를 트리거하기 위해 인스턴스 dradis에 new_contact? 드래 디스 클래스 Dradis.new의 인스턴스에 호출되는 NEW_METHOD :

때문에 이벤트가 않습니다, notify_listeners(:#{name}, *args)