问题描述
>> a = 5
=> 5
>> b = "hello, world!"
=> "hello, world!"
>> b.dup
=> "hello, world!"
>> a.dup
TypeError: can't dup Fixnum
from (irb):4:in `dup'
from (irb):4
我知道每次为新变量分配一个整数时,Ruby 都会创建一个副本,但是为什么 Numeric#dup
会引发错误?
I understand that Ruby will make a copy every time you assign an integer to a new variable, but why does Numeric#dup
raise an error?
这不会破坏抽象,因为所有对象都应该正确响应 .dup
吗?
Wouldn't this break abstraction, since all objects should be expected to respond to .dup
properly?
重写 dup
方法将解决问题,据我所知:
Rewriting the dup
method will fix the problem, as far as I can tell:
>> class Numeric
>> def dup()
>> self
>> end
>> end
这有我没有看到的缺点吗?为什么这不内置在 Ruby 中?
Does this have a downside I'm not seeing? Why isn't this built into Ruby?
推荐答案
Ruby 中的大多数对象都是通过引用传递的,并且可以被复制.例如:
Most objects in Ruby are passed by reference and can be dupped. Eg:
s = "Hello"
t = s # s & t reference to the same string
t.upcase! # modifying either one will affect the other
s # ==> "HELLO"
不过,Ruby 中有一些对象是直接的.它们是按值传递的,这个值只能有一个,因此不能被欺骗.它们是任何(小)整数、true
、false
、符号和 nil
.在 64 位系统上的 Ruby 2.0 中,许多浮点数也是立即数.
A few objects in Ruby are immediate, though. They are passed by value, there can only be one of this value and it therefore cannot be duped. These are any (small) integers, true
, false
, symbols and nil
. Many floats are also immediates in Ruby 2.0 on 64 bit systems.
在这个(荒谬的)示例中,任何42"都将保存相同的实例变量.
In this (preposterous) example, any "42" will hold the same instance variable.
class Fixnum
attr_accessor :name
alias_method :original_to_s, :to_s
def to_s
name || original_to_s
end
end
42.name = "The Answer"
puts *41..43 # => 41, The Answer, 43
由于您通常希望 something.dup.name = "new name"
除了使用 dup
获得的副本之外不会影响任何其他对象,因此 Ruby 选择不定义dup
立即数.
Since you would normally expect something.dup.name = "new name"
to not affect any other object than the copy obtained with dup
, Ruby chooses not to define dup
on immediates.
您的问题比看起来更复杂.在 ruby-core 上有一些讨论,关于如何使这更容易.此外,其他类型的 Numeric 对象(浮点数、大数、有理数和复数)虽然也不是立即数,但也不能被欺骗.
Your question is more complex than it appears. There was some discussion on ruby-core as to how this can be made easier. Also, other types of Numeric objects (floats, bignums, rationals and complex numbers) can not be duped although they are not immediates either.
注意 ActiveSupport(rails 的一部分)在所有对象上提供了 duplicable?
方法
Note that ActiveSupport (part of rails) provide the method duplicable?
on all objects
这篇关于为什么数字不支持.dup?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!