저는 C# 배경에서 왔고 Ruby에서 프로그래밍을 시작했습니다. 문제는 클래스에서 이벤트를 발생시켜 상황이 발생할 때 다양한 관찰자가 트리거 될 수 있도록하는 방법을 알아야한다는 것입니다.루비에서 이벤트 어떻게?
문제는 루비에 관한 책들도 이벤트를 언급하지 않고 혼자만의 예제를 제공한다는 것입니다. 누구든지 나를 도울 수 있습니까?
저는 C# 배경에서 왔고 Ruby에서 프로그래밍을 시작했습니다. 문제는 클래스에서 이벤트를 발생시켜 상황이 발생할 때 다양한 관찰자가 트리거 될 수 있도록하는 방법을 알아야한다는 것입니다.루비에서 이벤트 어떻게?
문제는 루비에 관한 책들도 이벤트를 언급하지 않고 혼자만의 예제를 제공한다는 것입니다. 누구든지 나를 도울 수 있습니까?
나는 약간의 C와 주로 루비로 GUI 라이브러리를 작성하려고 시도했다. 그것은 너무 천천히 끝내고 나는 결코 포기하지 않고 풀어 줬다. 하지만 C#보다 쉽게 만들려고 이벤트 시스템을 작성했습니다. 필자는 사용하기 쉽도록 두 번 다시 작성했습니다. 다소 도움이되기를 바랍니다.
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
는 말인지 정확히 모르겠어요하지만 당신은 아마 당신의 클래스에서 예외를 사용하여 특정 "이벤트"에 그들을 올릴 수 있습니다. GUI 개발을위한 이벤트가 필요한 경우 대부분의 GUI 프레임 워크는 자체 이벤트 처리 스타일을 정의합니다.
희망이 다소 답을하면 질문입니다.
질문에 대해서는 이미 대답했지만, 한 번 훑어보고 싶으면 observer이 표준 라이브러리에 내장되어 있습니다. 나는 작은 게임 프로젝트를 위해 그것을 과거에 사용했고, 그것은 아주 잘 작동한다.
매우 간단한 루비 리스너입니다. 이것은 .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!'
이 답변은 가장 루비 같은 느낌입니다. 강력한 형식의 언어를 모방하는 것이 아니라 언어의 동적 인 특성에 의존합니다. 사용하기 쉽고 이해하기 쉽고 멀티 캐스트를 지원합니다. –
공개 : 나는 당신이 접근하는 방법에 따라 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
는 기본적으로 비동기임을 알고 있어야합니다, 그래서 당신은 그냥이 스크립트를 실행하면 이벤트가 전달되기 전에 스크립트가 종료 할 수도 있습니다. 비동기 동작을 사용하지 않으려면 :
EventAggregator::Message.new("MessageType1", ["Some Stuff",2,3], false).publish
#The third parameter indicates async
는 희망이 사건 나는 관찰자 디자인 패턴을 사용하려면
에 도움이 될 수 있습니다. – Ash