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

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

Жанры

Программирование на языке 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

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

Лекарь Империи 7

Карелин Сергей Витальевич
7. Лекарь Империи
Фантастика:
городское фэнтези
аниме
боевая фантастика
попаданцы
5.00
рейтинг книги
Лекарь Империи 7

Глэрд VIII: Базис 2

Владимиров Денис
8. Глэрд
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Глэрд VIII: Базис 2

Наследие Маозари 5

Панежин Евгений
5. Наследие Маозари
Фантастика:
фэнтези
юмористическое фэнтези
5.00
рейтинг книги
Наследие Маозари 5

Звездная Кровь. Экзарх II

Рокотов Алексей
2. Экзарх
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Звездная Кровь. Экзарх II

Академия

Сай Ярослав
2. Медорфенов
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Академия

Я уже граф. Книга VII

Дрейк Сириус
7. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я уже граф. Книга VII

Барон отрицает правила

Ренгач Евгений
13. Закон сильного
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Барон отрицает правила

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон

Неудержимый. Книга XXX

Боярский Андрей
30. Неудержимый
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXX

Московское золото и нежная попа комсомолки. Часть Пятая

Хренов Алексей
5. Летчик Леха
Фантастика:
попаданцы
5.00
рейтинг книги
Московское золото и нежная попа комсомолки. Часть Пятая

Законы Рода. Том 11

Андрей Мельник
11. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 11

Зодчий. Книга II

Погуляй Юрий Александрович
2. Зодчий Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Зодчий. Книга II

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

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

Санек 3

Седой Василий
3. Санек
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Санек 3