>> 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为什么会引发错误?

既然所有的对象都应该正确响应.dup,这不会破坏抽象吗?

据我所知,重写dup方法将解决此问题:
>> class Numeric
>>   def dup()
>>     self
>>   end
>> end

这没有我看不到的缺点吗?为什么这不是Ruby内置的?

最佳答案

Ruby中的大多数对象都是通过引用传递的,可以被复制。例如:

s = "Hello"
t = s      # s & t reference to the same string
t.upcase!  # modifying either one will affect the other
s # ==> "HELLO"

不过,Ruby中的一些对象是即时的。它们是按值传递的,该值只能是其中一个,因此不能被复制。这些是任何(小)整数,truefalse,符号和nil。在64位系统上的Ruby 2.0中,许多浮点数也是立即数。

在这个(荒谬的)示例中,任何“42”将拥有相同的实例变量。
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

您的问题比看起来的要复杂。在ruby-core上有some discussion关于如何使它变得更容易。同样,其他类型的数值对象(浮点数,大数,有理数和复数)也不能被复制,尽管它们也不是立即数。

请注意,ActiveSupport(导轨的一部分)在所有对象上提供了duplicable?方法

关于ruby - 为什么数字不支持.dup?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1964143/

10-09 20:20
查看更多