Ruby получает доступ к методам производного класса из базового класса

У меня есть базовый класс в Ruby, у которого есть метод класса, который он унаследовал. Я хотел бы вызвать этот метод в базовом классе, но передать ему параметр, указанный производным классом, например:

class Base < SuperDuperClass
  super_duper_class_method :option => my_option_value

  def self.my_option_value
    raise "Method my_option_value must be overridden by all subclasses"
  end
end

class Derived < Base
  def self.my_option_value
    "My Derived Option Value"
  end
end

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

Любые идеи?


person alexsanford1    schedule 17.04.2012    source источник


Ответы (2)


Вы не были конкретны, когда сказали, что это не работает. Я полагаю, что вы получите исключение, когда будет определен базовый класс (а не при вызове my_option_value).

Я предлагаю вам передать имя метода как символ, а в SuperDuperClass вызвать функцию send on self для вызова производного метода.

class SuperDuperMethod
  def self.some_code
    self.class.__send__(options[:option])
  end
...
person Marlin Pierce    schedule 17.04.2012
comment
Вы также можете вызвать send вместо send. - person Marlin Pierce; 17.04.2012
comment
Я должен был упомянуть: SuperDuperClass взят из библиотеки, поэтому было бы лучше, если бы мне не приходилось исправлять его, чтобы заставить это работать. Когда я использую self.send в базовом классе вместо прямого вызова метода, я получаю NoMethodError - person alexsanford1; 17.04.2012
comment
Это не патчи для обезьян. Send делает то же самое, что и вызов метода. Мое плохое было то, что, поскольку вы вызываете метод класса, вам нужно отправить класс. Я отредактирую свой ответ. - person Marlin Pierce; 17.04.2012

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

person alexsanford1    schedule 26.11.2012