我怎样才能解决Ruby中缺少模块继承的问题?

时间:2011-05-23 17:18:09

标签: ruby metaprogramming

我正在尝试使用观察者模式在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使用onfire方法,但它们无法继承它们,因为模块不能拥有父项。我该怎么办?这不是红宝石般的吗?

我可以通过制作ComponentFooComponent类来实现这一目标,但我不能使用ComponentContainer或{{1}将它们混合到extend中}。

3 个答案:

答案 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