Чтение онлайн

на главную - закладки

Жанры

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

Кстати, не рекомендуем создавать структуру с именем

Tms
, так как уже есть предопределенный класс
Struct::Tms
.

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
), замораживается именно объект, а не переменная.

11.2. Более сложные механизмы

Не все в модели ООП, реализованной в Ruby, одинаково очевидно. Что-то сложнее, что-то применяется реже. Линия раздела для каждого программиста проходит в разных местах. В этой части главы мы попытались собрать те средства, которые не так просты или не так часто встречаются в программах.

Иногда вы задаетесь вопросом, можно ли решить на Ruby ту или иную задачу. Краткий ответ таков: Ruby — богатый, динамический, объектно-ориентированный язык с широким набором разумно ортогональных средств; если нечто можно сделать на каком-то другом языке, то, скорее всего, можно и на Ruby.

Теоретически все полные по Тьюрингу языки более или менее одинаковы. Весь смысл проектирования языков в поиске осмысленной, удобной нотации. Читателю, сомневающемуся в важности нотации, стоит попробовать написать интерпретатор LISP на языке COBOL или выполнить деление чисел, записанных римскими цифрами.

Конечно, мы не хотим сказать, что любая задача на Ruby решается элегантно или естественно. Попытайся мы высказать такое утверждение, кто-нибудь очень быстро докажет, что мы не правы.

В этом разделе мы поговорим также о реализации на Ruby различных стилей программирования, например функционального и аспектно-ориентированного. Мы не претендуем на роль экспертов в этих областях, просто приводим мнение других. Относитесь к этому с долей скепсиса.

11.2.1. Отправка объекту явного сообщения

В статическом языке вы считаете очевидным, что имя вызываемой функции «зашито» в программу, это часть исходного текста. Динамический язык обладает в данном отношении большей гибкостью.

При любом вызове метода вы посылаете объекту сообщение. Обычно эти сообщения так же жестко «зашиты» в код, как и в статическом языке, но это необязательно. Можно написать программу, которая во время выполнения решает, какой метод вызывать. Метод

send
позволяет использовать
Symbol
для представления имени метода.

Пусть, например, имеется массив объектов, который нужно отсортировать, причем в качестве ключей сортировки хотелось бы использовать разные поля. Не проблема - можно просто написать специализированные блоки для сортировки. Но хотелось бы найти более элегантное решение, позволяющее обойтись одной процедурой, способной выполнить сортировку по любому указанному ключу. В листинге 11.9 такое решение приведено.

Этот пример был написан для первого издания книги. Теперь метод

sort_by
стал стандартным и даже более эффективным, поскольку реализует преобразование Шварца (по имени известного гуру в языке Perl Рэндала Шварца) и сохраняет преобразованные значения вместо многократного их вычисления. Впрочем, листинг 11.9 по-прежнему дает пример использования метода
send
.

Листинг 11.9. Сортировка по любому ключу

class Person

 attr_reader :name, :age, :height

Поделиться:
Популярные книги

"Зарубежная фантастика 2024-4" Цикл "Люди льда". Компиляция. Книги 1-23

Сандему Маргит
Зарубежная фантастика 2024
Фантастика:
фэнтези
5.00
рейтинг книги
Зарубежная фантастика 2024-4 Цикл Люди льда. Компиляция. Книги 1-23

Дважды одарённый. Том X

Тарс Элиан
10. Дважды одаренный
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Дважды одарённый. Том X

Точка Бифуркации

Смит Дейлор
1. ТБ
Фантастика:
боевая фантастика
7.33
рейтинг книги
Точка Бифуркации

Философия. Книга вторая. Просветление экзистенции

Ясперс Карл Теодор
Научно-образовательная:
философия
5.00
рейтинг книги
Философия. Книга вторая. Просветление экзистенции

Паладин. (Трилогия)

Шелонин Олег Александрович
Паладин
Фантастика:
фэнтези
юмористическая фантастика
8.89
рейтинг книги
Паладин. (Трилогия)

Петлистые времена(Повести. Рассказы)

Лукин Евгений Юрьевич
Фантастика:
научная фантастика
5.00
рейтинг книги
Петлистые времена(Повести. Рассказы)

Игра

Анкай Виктория
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Игра

Старый знакомый

Шейнин Лев Романович
Детективы:
прочие детективы
7.43
рейтинг книги
Старый знакомый

Стрелок. Извлечение троих. Бесплодные земли

Кинг Стивен
Фантастика:
фэнтези
5.00
рейтинг книги
Стрелок. Извлечение троих. Бесплодные земли

Гримуар темного лорда IV

Грехов Тимофей
4. Гримуар темного лорда
Фантастика:
фэнтези
боевая фантастика
попаданцы
аниме
5.25
рейтинг книги
Гримуар темного лорда IV

Кодекс Охотника. Книга XXL

Винокуров Юрий
41. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXL

Светила

Каттон Элеанор
Проза:
историческая проза
7.58
рейтинг книги
Светила

Собрание сочинений. т.3.

Золя Эмиль
Проза:
классическая проза
5.00
рейтинг книги
Собрание сочинений. т.3.

Корабль смерти, Стальной человек и другие самые невероятные истории (сборник)

Матесон Ричард
Шедевры фантастики
Фантастика:
научная фантастика
ужасы и мистика
6.80
рейтинг книги
Корабль смерти, Стальной человек и другие самые невероятные истории (сборник)