Сделайте методы динамическими в ruby - PullRequest
0 голосов
/ 07 сентября 2018

Определите класс следующим образом. Я хочу позвонить one_method динамически. По умолчанию wow.one_method вызывает первый one_method. Если я хочу изменить поведение метода, просто вызовите redefine.

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

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

class Wow

    def one_method
        puts "hello Ruby"
    end

    def redefine(what="none")
        define_method :one_method do 
        puts what
        end
    end
end

wow = Wow.new
wow.redefine("Whatever I want.")

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Я бы порекомендовал достичь цели более каноническим способом, просто переопределите метод на самом экземпляре:

class Wow
  def one
    :one
  end
end

w = Wow.new
w.one
#=> :one

def w.one
  :two
end

w.one
#=> :two

Недостатки:

  • кэши таблиц поиска ваших методов будут удалены
  • код становится все более неясным и трудным для отладки

Альтернативы:

Я не знаю вашей реальной проблемы, но для вашего конкретного вопроса лучше параметризовать ваш one_method метод, просто чтобы получить аргумент для puts. Кроме того, вы можете передать блок, чтобы получить более детальный контроль над поведением.

0 голосов
/ 07 сентября 2018

Вы можете достичь этого с помощью class_eval или instance_eval:

class Wow

  def one_method
    puts "hello Ruby"
  end

  def redefine(what="none")
    self.class.class_eval do
      define_method :one_method do 
        puts what
      end
    end
  end
end

wow = Wow.new
wow.one_method #=> hello Ruby

wow.redefine("Whatever I want.")
wow.one_method #=> Whatever I want.

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

...