2009-03-03 13 views
16

मैं सी # पृष्ठभूमि से आया हूं, और रूबी में प्रोग्रामिंग शुरू कर दी है। बात यह है कि मुझे यह जानने की जरूरत है कि मैं अपनी कक्षाओं में घटनाओं को कैसे बढ़ा सकता हूं ताकि चीजों को होने की आवश्यकता होने पर विभिन्न पर्यवेक्षकों को ट्रिगर किया जा सके।रूबी में घटनाक्रम कैसे करें?

समस्या किताबें मैं रूबी पर भी घटनाओं का उल्लेख नहीं है, अकेले उदाहरण प्रदान करना है। क्या कोई मेरी मदद कर सकता है?

उत्तर

4

मैं एक छोटे से सी और मुख्य रूप से रूबी के साथ रूबी में एक जीयूआई पुस्तकालय लेखन की कोशिश की। यह इतनी धीमी हो गई कि मैंने छोड़ दिया और इसे कभी जारी नहीं किया। लेकिन मैंने इसके लिए एक इवेंट सिस्टम लिखा था कि मैंने सी # से आसान बनाने की कोशिश की। मैं इसका उपयोग करना आसान बनाने के लिए इसे दो बार फिर से लिखता हूं। मुझे आशा है कि यह कुछ हद तक सहायक होगा।

class EventHandlerArray < Array 
    def add_handler(code=nil, &block) 
    if(code) 
     push(code) 
    else 
     push(block) 
    end 
    end 
    def add 
    raise "error" 
    end 
    def remove_handler(code) 
    delete(code) 
    end 
    def fire(e) 
    reverse_each { |handler| handler.call(e) } 
    end 
end 

# with this, you can do: 
# event.add_handler 
# event.remove_handler 
# event.fire (usually never used) 
# fire_event 
# when_event 
# You just need to call the events method and call super to initialize the events: 
# class MyControl 
# events :mouse_down, :mouse_up, 
#   :mouse_enter, :mouse_leave 
# def initialize 
#  super 
# end 
# def when_mouse_up(e) 
#  # do something 
# end 
# end 
# control = MyControl.new 
# control.mouse_down.add_handler { 
# puts "Mouse down" 
# } 
# As you can see, you can redefine when_event in a class to handle the event. 
# The handlers are called first, and then the when_event method if a handler didn't 
# set e.handled to true. If you need when_event to be called before the handlers, 
# override fire_event and call when_event before event.fire. This is what painting 
# does, for handlers should paint after the control. 
# class SubControl < MyControl 
# def when_mouse_down(e) 
#  super 
#  # do something 
# end 
# end 
def events(*symbols) 
    # NOTE: Module#method_added 

    # create a module and 'include' it 
    modName = name+"Events" 
    initStr = Array.new 
    readerStr = Array.new 
    methodsStr = Array.new 
    symbols.each { |sym| 
    name = sym.to_s 
    initStr << %Q{ 
     @#{name} = EventHandlerArray.new 
    } 
    readerStr << ":#{name}" 
    methodsStr << %Q{ 
     def fire_#{name}(e) 
     @#{name}.fire(e) 
     when_#{name}(e) if(!e.handled?) 
     end 
     def when_#{name}(e) 
     end 
    } 
    } 
    eval %Q{ 
    module #{modName} 
     def initialize(*args) 
     begin 
      super(*args) 
     rescue NoMethodError; end 
     #{initStr.join} 
     end 
     #{"attr_reader "+readerStr.join(', ')} 
     #{methodsStr.join} 
    end 
    include #{modName} 
    } 
end 

class Event 
    attr_writer :handled 
    def initialize(sender) 
    @sender = @sender 
    @handled = false 
    end 
    def handled?; @handled; end 
end 
-1

मैं तुम्हें वास्तव में क्या मतलब है के बारे में सुनिश्चित नहीं कर रहा हूँ, लेकिन आप शायद अपनी कक्षाओं में अपवाद का उपयोग करें और कुछ "घटनाओं" पर उन्हें बढ़ा सकता है। यदि आपको जीयूआई विकास के लिए कार्यक्रम की आवश्यकता है तो अधिकांश जीयूआई ढांचे अपने स्वयं के आयोजन हैंडलिंग शैली को परिभाषित करते हैं।

आशा यह कुछ हद तक आप कर रहे हैं सवाल का जवाब।

+0

मैं ऑब्जर्वर डिजाइन पैटर्न का उपयोग करना चाहते करने में सहायक हो सकता है। – Ash

21

सवाल पहले से ही उत्तर दिया गया है, लेकिन वहाँ एक observer सही मानक पुस्तकालय में बनाया गया है, तो आप एक बार देख कि देने के लिए चाहते हैं। मैंने इसे अतीत में एक छोटी गेम परियोजना के लिए उपयोग किया है, और यह बहुत अच्छी तरह से काम करता है।

3

अत्यंत सरल रूबी श्रोता। यह .NET घटनाओं के लिए बिल्कुल एक प्रतिस्थापन नहीं है, लेकिन यह एक बहुत ही सरल श्रोता का एक अत्यंत सरल उदाहरण है।

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 

का उपयोग करें:

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 

आउटपुट:

The cow said 'moooo!' 
+1

यह उत्तर सबसे रूबी-आश लगता है। यह दृढ़ता से टाइप किए गए व्यक्ति को अनुकरण करने के बजाय भाषा की गतिशील प्रकृति पर निर्भर करता है, इसका उपयोग करना और समझना आसान है, और यह मल्टीकास्ट का समर्थन करता है। –

1

प्रकटीकरण: मैं event_aggregator मणि

के मेंटेनर हूँ तुम कैसे दृष्टिकोण करना चाहते हैं पर निर्भर करता है समस्या आप संभावित रूप से एक घटना योग का उपयोग कर सकते हैं ator। इस तरह आप किसी निश्चित प्रकार के संदेशों को प्रकाशित कर सकते हैं और फिर अपनी ऑब्जेक्ट्स उन प्रकारों को सुन सकते हैं जिन्हें आप प्राप्त करना चाहते हैं। यह कुछ मामलों में सामान्य घटनाओं से बेहतर हो सकता है क्योंकि आप अपनी वस्तुओं के बीच बहुत ढीला युग्मन प्राप्त करते हैं। घटना निर्माता और श्रोता को दूसरे के संदर्भ को साझा करने की आवश्यकता नहीं है।

एक मणि है कि आप के साथ इस event_aggregator कहा जाता है में मदद करता है नहीं है। इसके साथ आप निम्न कर सकते हैं:

#!/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 

जानते हैं कि यह डिफ़ॉल्ट रूप से async है रहो, इसलिए यदि आप सिर्फ इस स्क्रिप्ट को निष्पादित स्क्रिप्ट घटनाओं पारित कर रहे हैं इससे पहले कि बाहर निकलने के हो सकता है। async व्यवहार उपयोग को अक्षम करने के लिए:

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

उम्मीद है कि इस अपने मामले

संबंधित मुद्दे