2016-12-29 3 views
15

Я использую метод рубинового замораживания. Что касается определения замораживания, он замораживает значение объекта, на котором он вызывается. Мы не можем изменить значение этого объекта после него. Я должен достичь того же задач, у меня есть объект, и я уверен, выполнение следующего кода+ = оператор изменил замороженную строку

a = "Test" 
a.freeze 
a += "this string" 
puts a 

Это дает выходы следующим образом:

Test this string 
[Finished in 0.0s] 

Почему модифицируют свою замороженную строку?

+3

Возможный дубликат [Выемка переменных в Ruby, не работает] (http://stackoverflow.com/questions/17067171/freezing-variables-in-ruby- doesnt-work) – Manishh

+2

Переменные различаются; поэтому они называются переменными. –

+1

Я вижу, что это дубликат, но это хороший вопрос с хорошим ответом, из-за чего я неохотно использую на нем дуб-молот. Я предпочел бы отметить [номинированный экзамен] (http://stackoverflow.com/questions/17067171/freezing-variables-in-ruby-doesnt-work) как дубликат этого вопроса, хотя он старше - это не так чисто. –

ответ

46

Ничто не модифицируя замороженный String

Вы переназначения a к новому String с

a += "this string" 

, который внутренне же в Рубине, как

a = a + "this string" 

При добавлении два объекта String в Ruby, он создаст новую строку, содержащую результат (это нормальное поведение для + на большинстве объектов, которые его поддерживают). Это оставляет неизменным исходные значения «Test» и «this string». Исходная, замороженная строка (содержащая «Тест») останется в памяти до тех пор, пока не будет собран мусор. Его можно собрать, потому что вы потеряли все ссылки на него.

Если вы пытались изменить объект на месте, как это:

a << "this string" 

, то вы должны увидеть сообщение об ошибке RuntimeError: can't modify frozen String

В принципе, вы спутали a, локальную переменную с String объекта к которому он указывает. Локальные переменные могут быть повторно назначены в любое время независимо от объектов, хранящихся в Ruby. Вы можете проверить, что это произошло в вашем случае, проверив a.object_id до и после вашей линии a += ....

+4

Также стоит отметить: 'a.object_id' до и после совершенно разные. Это полезная диагностика, когда вещи ведут себя странно *, как массив с клонированными элементами. – tadman

2

сублимационной метод предотвращает вас от изменения объекта, он превращает объект в постоянной.

s1 = "its testing" 
s1.freeze 
puts "Object ID ===", s1.obejct_id 

Таким образом, после замораживания объекта попытка его модификации приводит к возникновению TypeError.

s1 << "testing again" 

это даст, RuntimeError: не может изменить замороженных снабжать струной, тетивой и т.п.

НО,

сублимационной работает на ссылки объекта, а не на переменной

s1 += "New Testing" 
puts "Object ID ===", s1.obejct_id 

будет указывать на новый объект, а также проверить его идентификатор объекта.

Для получения более подробной информации обратитесь к этому сайту, http://rubylearning.com/satishtalim/mutable_and_immutable_objects.html

Смежные вопросы