Присваивание связывает имя с объектом
Представим массив из двух чисел и переменную, которая на него ссылается. Если другой переменной присвоить значение первой, отдельный массив только от этого не появится. Оба имени будут указывать на один объект. Добавление элемента в этот массив станет видимым через каждое имя. Полезно рисовать не две одинаковые коробки, а одну коробку и две стрелки к ней. Такая схема помогает отделить объект от способа обращения к нему. Важно понимать, выполняет ли следующая операция изменение содержимого или создаёт новое значение. Внешне похожие строки программы могут иметь разные последствия.
Новое присваивание не равно изменению общего массива
Если второй переменной затем присвоить другой массив, меняется её связь с объектом. Первая переменная продолжает ссылаться на прежний массив, содержимое которого от этого не изменяется. Это различие важно и внутри методов. Локальное переназначение параметра само по себе не переназначает переменную вызывающего кода. Однако метод может изменить переданный изменяемый объект, и тогда последствие будет заметно снаружи. Поэтому при чтении метода полезно спрашивать, что именно он делает с данными. Название функции не заменяет понимания её поведения и документированных побочных эффектов.
Поверхностная копия не разделяет все вложенные объекты
Для обычного массива метод dup создаёт отдельный массив, но его элементы могут продолжать ссылаться на те же вложенные объекты. Например, два внешних массива способны содержать один общий внутренний массив. Изменение внутреннего содержимого тогда видно через обе структуры. При этом добавление нового элемента только во внешний массив относится уже к отдельной копии. Нельзя считать любую копию глубокой без проверки. Также запрет изменения внешнего объекта не обязательно делает неизменяемыми все вложенные данные. Выбор подхода зависит от задачи: иногда совместное использование намеренное, иногда нужны явно независимые части.
Попробуйте на практике
Нарисуйте на бумаге схему объектов для двух переменных и вложенного массива. Устанавливать Ruby и выполнять код необязательно.
- Изобразите один массив с двумя числами и две стрелки от разных имён. Добавьте элемент в общую коробку и подпишите, что увидит каждое имя.
- Перенаправьте вторую стрелку к новому массиву. Объясните, почему содержимое исходной коробки не изменилось от самого переназначения.
- Создайте две внешние коробки, которые ссылаются на одну внутреннюю. Отдельно смоделируйте добавление элемента во внешнюю копию и изменение общего внутреннего массива.
- Сформулируйте вопросы к методу обработки данных: меняет ли он переданный объект, создаёт ли копию и на каком уровне. Не полагайтесь только на название метода.
Как проверить результат. Схема различает имя, объект и вложенную ссылку. Вы можете объяснить, какие изменения общие, а какие относятся только к одной структуре.
Частые вопросы
Присваивание массива другой переменной создаёт независимую копию?
Нет. Само присваивание связывает второе имя с тем же объектом. Для копирования нужно отдельное действие.
После dup все вложенные данные независимы?
Для обычного массива нет: копирование поверхностное. Вложенные изменяемые объекты могут оставаться общими, и это нужно учитывать.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.