为什么`可复制?`定义它的方式?

eng*_*erk 10 ruby ruby-on-rails

我在Rails源代码中遇到过这个问题:

class Object
  def duplicable?
    true
  end
end

class NilClass
  begin
    nil.dup
  rescue TypeError    
    def duplicable?
      false
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

有了这个代码,即使dup被删除从对象,该对象响应duplicable?true.

我认为它可以重写为更简单的代码,如:

class Object
  def duplicable?
    repond_to?(:dup)
  end
end
Run Code Online (Sandbox Code Playgroud)

定义duplicable?使用begin...... 的优点是什么rescue

Ste*_*fan 7

定义duplicable?使用begin...... 的优点是什么rescue

尝试执行nil.dup以下操作时,2.4之前的Ruby引发了TypeError :

$ rbenv local 2.3.0

$ ruby --version
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]

$ ruby -e 'p nil.dup'
-e:1:in `dup': can't dup NilClass (TypeError)
    from -e:1:in `<main>'
Run Code Online (Sandbox Code Playgroud)

从Ruby 2.4开始,nil.dup只返回自己:

$ rbenv local 2.4.0

$ ruby --version
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin15]

$ ruby -e 'p nil.dup'
nil
Run Code Online (Sandbox Code Playgroud)

将方法定义放在内部rescue可确保该方法仅针对引发该方法的Ruby版本定义TypeError.

我认为它可以改写为更简单的代码,如:[...]

简单地检查接收器是否响应是dup不起作用的,因为nil- 作为Object- 确实响应dup,即使在2.3中.在TypeError为(是)从内部升高Object#dup:

VALUE rb_obj_dup(VALUE obj)
{
    VALUE dup;

    if (rb_special_const_p(obj)) {
        rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • @engineerk这个应该肯定被标记为正确的答案,而不是我的.请修改. (2认同)