Почему отсутствие оператора присваивания позволяет мне изменять константу Ruby без предупреждения компилятора?

StackOverflow https://stackoverflow.com/questions/670094

Вопрос

В следующих двух примерах я делаю то же самое, создавая постоянную строку и используя метод concat для ее изменения.Поскольку это константа, я ожидаю предупреждения компилятора, но получаю его только во втором примере, когда я использую оператор присваивания.Почему это происходит?

X = "hello"
X.concat(" world")
puts X # no warning

X = "hello"
X = X.concat(" world")
puts X # warning: already initialized

Поскольку метод concat изменяет строку на месте, это обычно то, что я бы сделал, поскольку нет необходимости использовать оператор присваивания.Итак, почему наличие оператора присваивания заставляет компилятор идентифицировать эти две операции как разные?

Это было полезно?

Решение

Это потому, что вы переопределяете новый X.Когда вы переопределяете константу, это выдает вам ошибку "уже инициализировано".Первый пример не выдает этой ошибки, потому что вы не переопределяете X, вы изменяете его.

Другие советы

В Ruby переменные по сути являются указателями на место в памяти, содержащее объект, а не на сам объект.Во втором примере вы инициализируете константу X указывать на объект в первой строке (X = "hello"), и во второй строке вы снова инициализируете константу, но она уже указывает на объект, поэтому вы получаете ошибку.

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

Если вы хотите сделать свою строку "реальной" константой, попробуйте "заморозить":

X = "foo".freeze        # => "foo" 
X.concat("bar")

TypeError: can't modify frozen string
    from (irb):2:in `concat'
    from (irb):2

Я действительно призываю вас читать Язык программирования Ruby.

Это происходит потому, что постоянная X хранит ли ссылка на String объект.В вашем первом примере вы изменяете внутреннее состояние String объект, но не ссылка, хранящаяся в константе.Во втором примере вы меняете ссылку, сохраненную константой, на новую String объект, который возвращается из concat способ.

Книга о кирке объясняет это здесь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top