我在 Rails 源代码中遇到过这个:
class Object
def duplicable?
true
end
end
class NilClass
begin
nil.dup
rescue TypeError
def duplicable?
false
end
end
end
使用此代码,即使从对象中删除了 dup
,该对象也会以 true
响应 duplicable?
。
我认为它可以重写为更简单的代码,例如:
class Object
def duplicable?
repond_to?(:dup)
end
end
使用 begin
...rescue
定义 duplicable?
有什么好处?
最佳答案
What is the merit of defining
duplicable?
usingbegin
...rescue
?
2.4 之前的 Ruby 在尝试 nil.dup
时引发了类型错误:
$ 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 版本定义该方法.
I think it can be rewritten to a simpler code like: [...]
简单检查接收者是否响应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));
}
// ...
}
关于ruby-on-rails - 为什么 `duplicable?` 是这样定义的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49321553/