首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Ruby中做事件?

如何在Ruby中做事件?
EN

Stack Overflow用户
提问于 2009-03-03 05:05:59
回答 4查看 15K关注 0票数 17

我有C#背景,刚刚开始用Ruby语言编程。问题是,我需要知道如何在我的类中引发事件,以便在需要发生事情时触发各种观察器。

问题是我写的关于Ruby的书甚至没有提到事件,更不用说提供例子了。有人能帮我吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-03-03 05:25:28

我试着用Ruby编写了一个GUI库,只用了一点C,主要是Ruby。它最终变得如此缓慢,我放弃了,从来没有发布过它。但是我为它写了一个事件系统,我试着让它比C#的更容易。我重写了几次,使它更容易使用。我希望它能有所帮助。

代码语言:javascript
复制
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
票数 4
EN

Stack Overflow用户

发布于 2009-03-03 08:22:32

这个问题已经得到了回答,但是如果你想看一下,标准库中有一个内置的observer。我过去曾在一个小游戏项目中使用过它,它运行得非常好。

票数 24
EN

Stack Overflow用户

发布于 2013-08-03 03:23:18

非常简单的Ruby监听器。这并不完全是.NET事件的替代品,但这是一个非常简单的侦听器的一个非常简单的示例。

代码语言:javascript
复制
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

要使用以下命令:

代码语言:javascript
复制
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

输出:

代码语言:javascript
复制
The cow said 'moooo!'
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/605169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档