Вы клонировали массив , содержащий Person
ссылки, но вы не изменили массив; Вы изменили сами Person
экземпляры. clone
- это так называемый «неглубокий клон», который копирует только объект-получатель, но ни один из объектов, чьи ссылки он может содержать.
В реальной логике: вы взяли лист бумаги, на котором написали «Дженни, Тимми». Затем вы скопировали его на другой лист бумаги. Затем вы взяли первый лист бумаги, нашли людей, на которых он ссылался, и дали им яблоко. Затем вы взяли второй лист бумаги, нашли на нем людей и задались вопросом, откуда взялись их яблоки. Но есть только один Тимми, только одна Дженни: вы даете в первом списке Дженни яблоко, во втором списке Дженни тоже есть.
Если вы хотите что-то клонировать, клонируйте Дженни .
array.map { |person|
person.clone.yield_self { |clone|
clone.email = clone.email.upcase
}
}
(Обратите внимание, что я не использовал clone.email.upcase!
. Причина - одна и та же причина снова и снова: если вы клонируете объект, они оба будут использовать одну и ту же строку для email
. upcase!
изменения этой строки, который будет в верхнем регистре электронной почты клона и электронной почты оригинала. Таким образом, мы создаем новую строку электронной почты для клона.)
Подобные вещи лучше всего понять, перейдя к визуализации с помощью этого инструмента . Тем не менее, инструмент запускает Ruby 2.2, который не знает о yield_self
; этот код эквивалентен:
array.map { |person|
clone = person.clone
clone.email = clone.email.upcase
clone
}
Вы могли бы также написать это, хотя это не будет отображаться так четко:
array.map(&:clone).map { |clone|
clone.email = clone.email.upcase
}