respond_to和respond_to_missing有何不同?

我很困惑何时使用这些方法。 来自respond_to? 文档:

如果obj响应给定方法,则返回true。 仅当可选的第二个参数的计算结果为true时,才会在搜索中包含私有方法。

如果未实现该方法,如Windows上的Process.fork,GNU / Linux上的File.lchmod等,则返回false。

如果没有定义方法,则response_to_missing? 调用方法并返回结果。

并且respond_to_missing?

Hook方法返回obj是否可以响应id方法。

见#respond_to?。

两种方法都有2个参数。
两种方法似乎都是一样的(检查某个对象是否响应给定的方法)所以为什么我们应该使用(have)两者?

定义’resond_to_missing?`让你有能力采取方法:

 class A def method_missing name, *args, &block if name == :meth1 puts 'YES!' else raise NoMethodError end end def respond_to_missing? name, flag = true if name == :meth1 true else false end end end [65] pry(main)> A.new.method :meth1 # => # 

为什么要respond_to? 不能这样做?

我猜:

respond_to? 检查方法是否在:

  1. 当前对象。
  2. 父对象。
  3. 包含的模块。

respond_to_missing? 检查方法是否:

  1. 通过method_missing定义:

通过一系列可能的方法:

 def method_missing name, *args, &block arr = [:a, :b, :c] if arr.include? name puts name else raise NoMethodError end end 

委托给不同的对象:

 class A def initialize name @str = String name end def method_missing name, *args, &block @str.send name, *args, &block end end 

2。 其他我不知道的方式。

应该在哪里定义/使用(我的猜测也是):

从1.9.3开始(我记得公平)只定义respond_to_missing? 但只使用respond_to?

最后的问题

我对吗? 我错过了什么吗? 纠正一切不好的事情和/或回答这个问题中提出的问题

respond_to_missing? 当您使用缺少方法的方法提供其他方法时,应该更新。 这将使Ruby解释器更好地理解新方法的存在。

实际上,没有使用respond_to_missing? ,你无法获得使用method

Marc-André发表了一篇关于respond_to_missing? 的精彩文章 respond_to_missing?

为了response_to? 要返回true,可以将其专门化,如下所示:

 class StereoPlayer # def method_missing ... # ... # end def respond_to?(method, *) method.to_s =~ /play_(\w+)/ || super end end p.respond_to? :play_some_Beethoven # => true 

这样更好,但它仍然没有使play_some_Beethoven的行为与方法完全相同。 确实:

 p.method :play_some_Beethoven # => NameError: undefined method `play_some_Beethoven' # for class `StereoPlayer' 

Ruby 1.9.2引入了respond_to_missing? 这为问题提供了一个干净的解决方案。 而不是专门的respond_to? 一个专门的respond_to_missing? 。 这是一个完整的例子:

 class StereoPlayer # def method_missing ... # ... # end def respond_to_missing?(method, *) method =~ /play_(\w+)/ || super end end p = StereoPlayer.new p.play_some_Beethoven # => "Here's some_Beethoven" p.respond_to? :play_some_Beethoven # => true m = p.method(:play_some_Beethoven) # => # # m acts like any other method: m.call # => "Here's some_Beethoven" m == p.method(:play_some_Beethoven) # => true m.name # => :play_some_Beethoven StereoPlayer.send :define_method, :ludwig, m p.ludwig # => "Here's some_Beethoven" 

另请参阅始终定义respond_to_missing? 当重写method_missing时 。