Книга: Программирование на языке Ruby

11.1.15. Замораживание объектов

11.1.15. Замораживание объектов

Иногда необходимо воспрепятствовать изменению объекта. Это позволяет сделать метод freeze (определенный в классе Object). По существу, он превращает объект в константу.

Попытка модифицировать замороженный объект приводит к исключению TypeError. В листинге 11.8 приведено два примера.

Листинг 11.8. Замораживание объекта

str = "Это тест. "
str.freeze
begin
 str << " He волнуйтесь." # Попытка модифицировать.
rescue => err
 puts "#{err.class} #{err}"
end
arr = [1, 2, 3]
arr.freeze
begin
 arr << 4 # Попытка модифицировать.
rescue => err
 puts "#{err.class} #{err}"
end
# Выводится:
# TypeError: can't modify frozen string
# TypeError: can't modify frozen array

Однако имейте в виду, что метод freeze применяется к ссылке на объект, а не к переменной! Это означает, что любая операция, приводящая к созданию нового объекта, завершится успешно. Иногда это противоречит интуиции. В примере ниже мы ожидаем, что операция += не выполнится, но все работает нормально. Дело в том, что присваивание — не вызов метода. Эта операция воздействует на переменные, а не на объекты, поэтому новый объект создается беспрепятственно. Старый объект по-прежнему заморожен, но переменная ссылается уже не на него.

str = "counter-"
str.freeze
str += "intuitive" # "counter-intuitive"
arr = [8, 6, 7]
arr.freeze
arr += [5, 3, 0, 9] # [8, 6, 7, 5, 3, 0, 9]

Почему так происходит? Предложение a += x семантически эквивалентно a = a + x. При вычислении выражения a + x создается новый объект, который затем присваивается переменной a! Все составные операторы присваивания работают подобным образом, равно как и другие методы. Всегда задавайте себе вопрос: «Что я делаю — создаю новый объект или модифицирую существующий?» И тогда поведение freeze не станет для вас сюрпризом.

Существует метод frozen?, который сообщает, заморожен ли данный объект.

hash = { 1 => 1, 2 => 4, 3 => 9 }
hash.freeze
arr = hash.to_a
puts hash.frozen?  # true
puts arr.frozen?   # false
hash2 = hash
puts hash2.frozen? # true

Как видите (на примере hash2), замораживается именно объект, а не переменная.

Оглавление книги


Генерация: 1.055. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз