我正在尝试使用观察者模式在Ruby中创建一个组件系统。组件必须定义为模块,因为它们只存在于ComponentContainer
中。但是Component
有一些方法,我希望在某种基类中定义,但我不能这样做,因为它们是模块。
这是我想做的事情:
module Component
def self.on(event, &block)
#definition..
end
def self.fire(event)
#pass event to subscribers
end
end
module FooComponent < Component
on :foo_event do |param1, param2|
#...
end
end
不同类型的Component
使用on
和fire
方法,但它们无法继承它们,因为模块不能拥有父项。我该怎么办?这不是红宝石般的吗?
我可以通过制作Component
和FooComponent
类来实现这一目标,但我不能使用ComponentContainer
或{{1}将它们混合到extend
中}。
答案 0 :(得分:3)
一种干净的方法是使用extend
钩子方法抽象出Module#included
的使用。在模块上调用此方法,该模块引用包含它的基础。这段代码的作用是创建一个Component
模块,该模块使用所需的方法自动扩展基础:
module Component
def self.included(base)
base.extend Methods
end
module Methods
def on(event, &block)
# ...
end
def fire(event)
# ...
end
end
end
module FooComponent
include Component
on :foo_event do |param1, param2|
# ...
end
end
答案 1 :(得分:2)
如果您创建了一个名为BaseComponent的单独模块,该模块定义了所有组件模块应具有的基本方法,然后在您的自定义组件中包含该BaseComponent。
然后,您仍然可以将这些自定义组件混合到ComponentContainer类中。
答案 2 :(得分:2)
您可以将Component
的方法扩展到“子”模块中:
module Component
extend self # (only if you also want to allow calling via Component.on like in the original example)
def on(event, &block)
#definition..
end
def fire(event)
#pass event to subscribers
end
end
module FooComponent
extend Component
on :foo_event do |param1, param2|
#...
end
end