Как я могу обойти отсутствие наследования модулей в Ruby? - PullRequest
2 голосов
/ 23 мая 2011

Я пытаюсь создать систему компонентов в 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 s используют методы on и fire, но они не могут их наследовать, потому что у модулей не может быть родителей.Что я должен делать?Разве это не похоже на рубин?

Я мог бы заставить это работать, создав классы Component и FooComponent, но тогда я не могу смешать их в ComponentContainer, используя extend или include.

Ответы [ 3 ]

3 голосов
/ 23 мая 2011

Простой способ сделать это - абстрагироваться от использования extend с помощью метода Module#included hook.Этот метод вызывается в модуле со ссылкой на базу, которая его включает.Этот код создает модуль 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
2 голосов
/ 23 мая 2011

Вы можете расширить методы 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
2 голосов
/ 23 мая 2011

Что если вы создали отдельный модуль с именем BaseComponent, который определил базовые методы, которые должны быть у всех компонентных модулей, а затем в ваших пользовательских компонентах включите этот BaseComponent.

Тогда вы все равно сможете смешивать эти пользовательские компоненты с классом ComponentContainer.

...