0

今日の@avdiのRubyTapasエピソードから次のコードを取得しました。

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呼び出すための引数だと思いました。eventDradis

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

4

2 に答える 2

1

私はエピソードを見ませんでしたが、見てください、それはすぐそこにあります。

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

eventからnew_contact呼び出す別のメソッド()を定義するメソッドです。notify_listenersEventful

マクロモジュールのイベントメソッドをトリガーします

正しくない。そのメソッドはかなり前にその作業を終了し、再び呼び出されることはありません。module_eval/を使用して新しいメソッドを生成し、defその新しいメソッド(new_contact)が呼び出されます。

クラスが解析されてロードされるeventときに、メソッドが1回だけ実行されることを理解することが重要です。Dradisのすべてのインスタンス化で実行されるわけではありませんDradis

于 2012-11-23T22:13:59.793 に答える
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)

于 2012-11-23T22:54:56.417 に答える