Большинство объектов в Ruby передаются по ссылке и могут быть сброшены. Например:
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
. Многие типы с плавающей точкой также доступны в Ruby 2.0 в 64-битных системах.
В этом (нелепом) примере любой «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
сразу.
Ваш вопрос сложнее, чем кажется. Было некоторое обсуждение о том, как это можно сделать проще. Кроме того, другие типы числовых объектов (числа с плавающей запятой, числовые значения, рациональные и комплексные числа) не могут быть дублированы, хотя они также не являются непосредственными.
Обратите внимание, что ActiveSupport (часть рельсов) предоставляет метод duplicable?
для всех объектов