Модули ruby: использование данных из определения класса в модуле - PullRequest
0 голосов
/ 05 августа 2010

У меня есть модуль, который хочет использовать данные, предоставленные классом, который их включил, - но на уровне класса, а не на уровне экземпляра.

цель состоит в том, чтобы предоставить метаданные класса модулю, который включен в этот класс, чтобы модуль мог использовать метаданные во время включенного вызова.

это работает:

module Bar
  def value
    @value
  end

  def baz
    puts "the value is: #{value}"
  end
end

module Foo
  def self.included(mod)
    mod.extend(Bar)
    mod.baz
  end
end

class MyClass
  @value = "my class defined this"
  include Foo
end

вывод этого кода

the value is: my class defined this

Я не уверен, является ли использование @value хорошим или нет ... Мне кажется странным, что я требую, чтобы это было установлено до того, как include Foo произойдет, а не с технической точки зрения (я знаю, почему это необходимо сделать в этом порядке), но с точки зрения идиоматичности или удобства использования.

... есть ли лучший способ / более идиоматический способ сделать это?

Ответы [ 2 ]

2 голосов
/ 05 августа 2010

Если вы действительно хотите использовать метаданные класса в тот момент, когда вы включаете модуль, учитывая, что «включенный» метод выполняется в своей собственной области, лучше всего иметь метод класса, предоставляющий ему метаданные.

Кроме того, если метаданными не будут манипулировать, лучше объявить их как константу.

module Bar
  def self.included(base)
    puts "the value is: #{base.metadata}"
  end
end

class MyClass
  VALUE = "MyClass metadata"

  def self.metadata
    VALUE
  end

  include Bar
end

class OtherClass
  VALUE = "OtherClass metadata"

  def self.metadata
    VALUE
  end

  include Bar
end

Конечно, вы можете объявить метаданные так, как хотите, если они доступны для метода класса вашему модулю.

Кроме того, такого рода манипулирование метаданными в методе «включенного» модуля не распространено, и необходимость упорядочения ваших утверждений на уровне класса немного хрупкая, поэтому вы можете попытаться найти другое решение для вместо этого ваша первоначальная проблема.

1 голос
/ 05 августа 2010

Если вы хотите, чтобы класс передал аргумент в mixin, то почему бы не использовать одну из конструкций Ruby, которая на самом деле позволяет разрешать передачу аргумента?

class Object
  private

  def Bar(metadata)
    Module.new do
      include Bar

      define_singleton_method(:included) do |base|
        puts "the value is: #{metadata}"
      end
    end
  end
end

module Bar
  # put common behavior here
end

class MyClass
  include Bar 'MyClass metadata'
end

class OtherClass
  include Bar 'OtherClass metadata'
end

Это довольно распространенная идиома, например, , используемая библиотекой delegate в stdlib .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...