Что константы Ruby действительно означает? Следующий код не показывает 'постоянного' атрибута. Предупреждение там, но я все еще добираюсь для изменения то, к чему относится A.
A = 1
puts A # => 1
A = 2 # warning: already initialized constant A
puts A # => 2
Или константы Ruby, просто признак без осуществления?
Правильно, -константы такие же, как -переменные в рубине, но при их изменении выдается предупреждение.
Также, есть одна разница с простыми переменными: Вы можете получить доступ к константам, даже если они определены внутри другого класса или модуля, например, при использовании этого фрагмента:
module Constants
PI = 3,1415
other = "variable"
end
Вы можете обратиться к PI
, сделав Constants::PI
, в то время как Constants::other
не будет работать.
Да, рубиновые константы не принуждаются, кроме как печатать это предупреждение.
"Constant" - это действительно неправильное название, наиболее важным аспектом "Constants" Рубина является не их неизменяемость, а правила поиска.
смотрите: http://coderrr.wordpress.com/2008/03/11/constant-name-resolution-in-ruby/
Правильно -- присваивание константы - это предупреждение, а не ошибка; "константы" - это просто индикатор того, как вы должны что-то использовать, а не правило, которое вы так используете.
Это может звучать ужасно, исходя из мира статического программирования, но это очень полезно в различных средствах метапрограммирования, и это позволяет использовать вещи, которые в противном случае были бы совершенно невозможны в статических языках.
Тем не менее, если Вы действительно хотите, чтобы люди держали свои грязные руки подальше от Ваших ссылок, Вы можете использовать Object#freeze
. Все равно ничего страшного в том, чтобы изменить то, на что указывает ссылка, просто нельзя изменить содержимое самой ссылки:
irb(main):001:0> class Fruit; attr_accessor :name; end
=> nil
irb(main):002:0> f = Fruit.new
=> #<Fruit:0xb7e06570>
irb(main):003:0> f.name = "apple"
=> "apple"
irb(main):004:0> f.freeze # After freeze, can't touch this Fruit.
=> #<Fruit:0xb7e06570 @name="apple">
irb(main):005:0> f.name = "banana"
TypeError: can't modify frozen object # Kablammo!
from (irb):5:in `name='
from (irb):5