Ссылки на объекты Ruby и ссылки на коллекции - PullRequest
2 голосов
/ 26 февраля 2012

Я просматривал «Обоснованный рубин» и запутался в следующем примере.

Предположим, у нас есть массив строк:

    numbers = ["one", "two", "three"]

Если я замораживаю этот массив, я не могу сделать следующее:

    numbers[2] = "four"

Это утверждение являетсяОшибка времени выполнения, но это:

    numbers[2].replace("four")

нет.

В книге объясняется, что в первом из двух последних утверждений мы пытаемся получить доступ к массиву.Это меня смутило, потому что я думал, что мы пытаемся получить доступ к третьему элементу массива, который является строковым объектом.И чем это отличается от последнего утверждения?

Ответы [ 2 ]

5 голосов
/ 26 февраля 2012

Это отличается, потому что в утверждении, которое работает, вы звоните String#replace.Как и следовало ожидать, вызов Array#replace завершится с ошибкой .

numbers.replace [1,2,3]
TypeError: can't modify frozen array

Ссылка на объект в любом данном индексе массива может быть произвольно сложной, и это не работа замороженного массивачтобы эти объекты не менялись ... он просто хочет, чтобы массив не менялся.Вы можете видеть это:

ree-1.8.7> numbers[2].object_id
 => 2149301040 
ree-1.8.7> numbers[2].replace "four"
 => "four" 
ree-1.8.7> numbers[2].object_id
 => 2149301040

numbers[2] имеет тот же object_id после выполнения String#replace;Массив на самом деле не изменился.

0 голосов
/ 26 февраля 2012

Массив - это список идентификаторов объектов.Строка # replace является особенной - она ​​изменяет строку, но сохраняет object_id.Таким образом, список object_id не меняется, и массив не обнаруживает никаких изменений.

Вы можете заморозить каждую строку массива.Строка # replace будет приводить к ошибке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...