2009-03-03 8 views
16

Ich komme aus einem C# Hintergrund und habe gerade mit der Programmierung in Ruby begonnen. Die Sache ist die, dass ich wissen muss, wie ich Ereignisse in meinen Klassen auslösen kann, so dass verschiedene Beobachter ausgelöst werden können, wenn Dinge passieren müssen.Wie Ereignisse in Ruby zu tun?

Das Problem ist, die Bücher, die ich auf Ruby habe, erwähnen nicht einmal Ereignisse, ganz zu schweigen von Beispielen. Kann mir jemand helfen?

Antwort

4

Ich habe versucht, eine GUI-Bibliothek in Ruby mit ein wenig C und vor allem Ruby zu schreiben. Es endete so langsam, dass ich aufgab und es nie wieder veröffentlichte. Aber ich habe ein Event-System dafür geschrieben, das ich einfacher zu machen versuchte als C#. Ich habe es ein paar Mal umgeschrieben, um es einfacher zu machen. Ich hoffe es ist etwas hilfreich.

-1

Ich bin mir nicht sicher, was Sie genau meinen, aber Sie könnten wahrscheinlich Ausnahmen in Ihren Klassen verwenden und sie auf bestimmte "Ereignisse" erhöhen. Wenn Sie ein Ereignis für die GUI-Entwicklung benötigen, definieren die meisten GUI-Frameworks ihren eigenen Event-Handling-Stil.

Hoffe, dass dies etwas Antworten Sie sind Frage.

+0

ich den Observer Design Muster verwenden möchten. – Ash

21

Die Frage wurde bereits beantwortet, aber es gibt ein observer direkt in die Standardbibliothek eingebaut, wenn Sie das sehen wollen. Ich habe es in der Vergangenheit für ein kleines Spielprojekt verwendet, und es funktioniert sehr gut.

3

Extrem einfacher Ruby-Listener. Dies ist nicht gerade ein Ersatz für .NET-Ereignisse, aber dieses ist ein extrem einfaches Beispiel für einen sehr einfachen Listener.

module Listenable 

    def listeners() @listeners ||= [] end 

    def add_listener(listener) 
     listeners << listener 
    end 

    def remove_listener(listener) 
     listeners.delete listener 
    end 

    def notify_listeners(event_name, *args) 
     listeners.each do |listener| 
      if listener.respond_to? event_name 
       listener.__send__ event_name, *args 
      end 
     end 
    end 

end 

zu benutzen:

class CowListenable 
    include Listenable 

    def speak 
     notify_listeners :spoken, 'moooo!' 
    end 

end 

class CowListener 

    def initialize(cow_listenable) 
     cow_listenable.add_listener self 
    end 

    def spoken(message) 
     puts "The cow said '#{message}'" 
    end 

end 

cow_listenable = CowListenable.new 
CowListener.new(cow_listenable) 
cow_listenable.speak 

Ausgang:

The cow said 'moooo!' 
+1

Diese Antwort fühlt sich am meisten rubinisch an. Es basiert auf der dynamischen Natur der Sprache, anstatt eine stark typisierte zu emulieren, es ist einfach zu verwenden und zu verstehen und es unterstützt Multicast. –

1

Disclosure: Ich bin der Maintainer des event_aggregator gem

Je nachdem, wie Sie die nähern wollen Problem könnten Sie möglicherweise eine Ereignisaggregation verwenden Ator. Auf diese Weise können Sie Nachrichten eines bestimmten Typs veröffentlichen und dann Ihre Objekte auf die Typen warten lassen, die sie empfangen sollen. Dies kann in bestimmten Fällen besser als normale Ereignisse sein, weil Sie eine sehr lockere Verbindung zwischen Ihren Objekten erhalten. Der Ereignisproduzent und der Listener müssen keinen Verweis auf den anderen freigeben.

Es gibt ein Juwel, das Ihnen dabei hilft event_aggregator genannt. Mit ihm können Sie wie folgt vorgehen:

#!/usr/bin/ruby 

require "rubygems" 
require "event_aggregator" 

class Foo 
    include EventAggregator::Listener 
    def initialize() 
     message_type_register("MessageType1", lambda{|data| puts data }) 

     message_type_register("MessageType2", method(:handle_message)) 
    end 

    def handle_message(data) 
     puts data 
    end 

    def foo_unregister(*args) 
     message_type_unregister(*args) 
    end 
end 

class Bar 
    def cause_event 
     EventAggregator::Message.new("MessageType1", ["Some Stuff",2,3]).publish 
    end 
    def cause_another_event 
     EventAggregator::Message.new("MessageType2", ["Some More Stuff",2,3]).publish 
    end 
end 

f = Foo.new 

b = Bar.new 
b.cause_event 
b.cause_another_event 
# => Some Stuff 
    2 
    3 
# => Some More Stuff 
    2 
    3 

Beachten Sie, dass es async ist standardmäßig, wenn Sie also nur dieses Skript ausführen beenden das Skript könnte, bevor die Ereignisse übergeben werden. So deaktivieren Sie die Verwendung asynchroner Verhalten:

EventAggregator::Message.new("MessageType1", ["Some Stuff",2,3], false).publish 
#The third parameter indicates async 

Hoffentlich kann dies hilfreich sein, in Ihrem Fall