response_to和response_to_missing有何不同? [英] How are respond_to and respond_to_missing different?

查看:205
本文介绍了response_to和response_to_missing有何不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对何时使用每种方法感到困惑. 从respond_to?文档:

I'm confused when to use each of this methods. From respond_to? documentation:

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

Returns true if obj responds to the given method. Private methods are included in the search only if the optional second parameter evaluates to true.

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

If the method is not implemented, as Process.fork on Windows, File.lchmod on GNU/Linux, etc., false is returned.

如果未定义方法,是否为response_to_missing?方法被调用并 结果返回.

If the method is not defined, respond_to_missing? method is called and the result is returned.

respond_to_missing?:

Hook方法可返回 obj 是否可以响应 id 方法或 不是.

Hook method to return whether the obj can respond to id method or not.

请参阅#respond_to?.

See #respond_to?.

两个方法都带有2个参数.
两种方法似乎都是同一件事(检查某个对象是否响应给定的方法),为什么我们要同时使用(拥有)这两种方法呢?

Both methods takes 2 arguments.
Both methods seems to the same thing(check if some object respond to given method) so why we should use(have) both?

定义"resond_to_missing?"使您能够采用方法:

Defining 'resond_to_missing?` gives you ability to take methods:

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
# => #<Method: A#meth1>

为什么respond_to?无法执行此操作?

Why respond_to? couldn't do this?

respond_to?检查方法是否在以下位置:

respond_to? checks if method is in:

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

respond_to_missing?检查方法是否为:

  1. 通过method_missing定义:

通过一系列可能的方法:

Via array of possible methods:

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.我不知道的其他方式.

2 . Other way that I'm not aware of.

从1.9.3开始(我记得还不错)仅定义respond_to_missing?,但仅使用respond_to?

Starting from 1.9.3(as fair I remember) define only respond_to_missing? but use only respond_to?

我是对的吗?我错过了什么吗?纠正所有不良情况和/或回答此问题中提出的问题.

Am I right? Did I missed something? Correct everything that is bad and/or answer questions asked in this question.

推荐答案

respond_to_missing?.这将使Ruby解释器更好地了解新方法的存在.

respond_to_missing? is supposed to be updated when you make available additional methods using the method missing technique. This will cause the Ruby interpreter to better understand the existence of the new method.

实际上,如果不使用respond_to_missing?,就无法使用

In fact, without using respond_to_missing?, you can't get the method using method.

Marc-André发表了一篇很棒的文章有关respond_to_missing?.

为了响应?要返回true,可以对其进行专门化,如下所示:

In order for respond_to? to return true, one can specialize it, as follows:

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的行为完全像一种方法.确实:

This is better, but it still doesn’t make play_some_Beethoven behave exactly like a method. Indeed:

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?.这是一个完整的示例:

Ruby 1.9.2 introduces respond_to_missing? that provides for a clean solution to the problem. Instead of specializing respond_to? one specializes respond_to_missing?. Here’s a full example:

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) # => #<Method: StereoPlayer#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"

另请参见始终定义response_to_missing吗?覆盖method_missing时.

这篇关于response_to和response_to_missing有何不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆