【问题标题】:Make methods dynamic in ruby在 ruby​​ 中使方法动态化
【发布时间】:2018-09-07 09:29:04
【问题描述】:

如下定义一个类。我想动态调用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.")

【问题讨论】:

  • 您能澄清一下您的问题吗?什么,确切地说是您想要实现的?例如,我不清楚您是要为Wow 的所有实例重新定义方法还是只为一个实例重新定义该方法。您能否提供示例输入和输出来展示您想要实现的目标?你能提供一组代码应该做什么的规则,包括极端情况和边缘情况吗?此外,“它会报告错误”的描述不够精确,无法帮助您。它报告什么错误?在什么情况下会出现这些错误?错误消息说什么? …
  • ... 这些错误指的是哪一行?哪种方法?另外,什么是“函数类型属性”?它不是 Ruby 语言规范、RubySpec、核心库和标准库的 RDoc 文档、Ruby Programming Language 书或 Programming Ruby中存在的概念> book,通常被认为是定义 Ruby 的术语和行为的权威来源。从我得到的谷歌结果来看,它似乎是一个名为“Bokeh”的 Python 库中的概念,这与这里有什么关系?
  • 最后一个问题:这与dynamic-programming 有什么关系?您的代码中没有分而治之,没有缓存,没有回溯,这些通常是动态编程算法的主要成分。
  • @JörgWMittag 非常感谢您的详细考虑。它与动态编程无关,这是一个错字。请参阅 Surya 给出的答案。

标签: ruby oop dynamic


【解决方案1】:

您可以通过class_evalinstance_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 在接收器上定义了实例方法,并且是类的实例方法,因此您必须在要重新定义方法的对象的特征类上调用它。

【讨论】:

  • 你能解释一下这比使用define_singleton_method 更旧的(诚然质量非常低的)答案中的建议吗?
  • @Surya 非常感谢。还要感谢 Jorg W Mittag
【解决方案2】:

我建议以更规范的方式实现您的目标,只需重新定义实例本身的方法:

class Wow
  def one
    :one
  end
end

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

def w.one
  :two
end

w.one
#=> :two

缺点是:

  • 您的方法查找表缓存将被删除
  • 代码变得越来越晦涩难懂

替代方案:

我不知道您的真正问题,但对于您的特定问题,最好参数化您的 one_method 方法,以便接收 puts 的参数。此外,您可以传递一个块,因此您将获得对行为的更细粒度的控制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 2013-07-01
    • 1970-01-01
    • 2010-10-18
    • 2013-03-29
    相关资源
    最近更新 更多