Уловить это? Константа была добавлена одновременно с локальной переменной.
Нет, он не был добавлен, как и локальная переменная.
Был добавлен единственный объект, к которому относятся и константа, и локальная переменная, но ни константа, ни локальная переменная не изменились. Вы не можете изменить или изменить переменную или константу в Ruby (по крайней мере, не так, как подразумевает ваш вопрос), единственное, что вы можете изменить, — это объекты.
Единственные две вещи, которые вы можете делать с переменными или константами, — это разыменовывать их и присваивать им значения.
Константа здесь является отвлекающим маневром, она совершенно не имеет отношения к приведенному примеру. Единственное, что имеет значение, это то, что во всем примере есть только один объект. Этот единственный объект доступен под двумя разными именами. Если объект меняется, то объект меняется. Период. Он не разделяется таинственным образом на две части. Какое имя вы используете для просмотра измененного объекта, не имеет значения. В любом случае есть только один объект.
Это работает точно так же, как и в любом другом языке программирования: если у вас есть несколько ссылок на изменяемый объект, скажем, в Python, Java, C#, C++, C, Lisp, Smalltalk, JavaScript, PHP, Perl или где-то еще, то любое изменение к этому объекту будет виден независимо от того, какая ссылка используется, даже если некоторые из этих ссылок являются final
или const
или как-то еще, что этот конкретный язык называет это.
Просто так работает разделяемое изменяемое состояние, и это лишь одна из многих причин, почему разделяемое изменяемое состояние — это плохо.
В Ruby вы обычно можете вызвать метод freeze
для любого объекта, чтобы сделать его неизменяемым. Однако, опять же, здесь вы изменяете объект, так что любой, у кого есть ссылка на этот объект, внезапно обнаружит, что объект стал неизменяемым. Поэтому на всякий случай вам нужно сначала скопировать объект, вызвав dup
. Но, конечно, этого тоже недостаточно, если вы думаете о массиве, например: если вы dup
массив, вы получите другой массив, но объекты внутри array все те же, что и в исходном массиве. И если вы freeze
массив, то вы больше не можете изменять массив, но объекты в массиве вполне могут быть изменены:
ORIG = ['Hello']
CLONE = ORIG.dup.freeze
CLONE[0] << ', World!'
CLONE # => ['Hello, World!']
Это общее изменяемое состояние для вас. Единственный способ избежать этого безумия — либо отказаться от разделяемого состояния (например, акторное программирование: если его никто не видит, то не имеет значения, как часто и когда оно меняется), либо от изменяемого состояния (т. е. функционального программирования: если оно никогда не изменяется). меняется, то не имеет значения, сколько других это увидит).
Тот факт, что одна из двух переменных в исходном примере на самом деле является константой, совершенно не имеет отношения к проблеме. Между переменной и константой в Ruby есть два основных различия: у них разные правила поиска, и константы генерируют предупреждение, если им присваивается значение более одного раза. Но в этом примере правила поиска не имеют значения, а константа присваивается только один раз, поэтому в этом случае действительно нет разницы между переменной и константой.
person
Jörg W Mittag
schedule
10.06.2010