我在Rails源代码中遇到过这个问题:
class Object
def duplicable?
true
end
end
class NilClass
begin
nil.dup
rescue TypeError
def duplicable?
false
end
end
end
使用此代码,即使从对象中删除dup
,该对象也会使用duplicable?
响应true
。
我认为它可以重写为更简单的代码,如:
class Object
def duplicable?
repond_to?(:dup)
end
end
使用duplicable?
... begin
定义rescue
的优点是什么?
答案 0 :(得分: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>'
从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
将方法定义放在rescue
中可确保仅为引发TypeError
的Ruby版本定义该方法。
我认为它可以改写为更简单的代码,如:[...]
只需检查接收方是否响应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));
}
// ...
}
:
round
答案 1 :(得分:2)
nil
回复 dup
明确抛出TypeError
(反过来,与NoMethodError
无关。)[更正] :在2.4之前回复dup
,积分转到@Stefan。]
NilClass.instance_method(:dup)
#⇒ #<UnboundMethod: NilClass(Kernel)#dup>
目标是使用duplicable?
回复false
,除非 NilClass#dup
被城市中的另一个猴子修补程序覆盖。 [更正:将“另一个猴子修补器”改为“Matz”:)]