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

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

Жанры

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

Все животные равны, но некоторые равнее других.

Джордж Оруэлл, «Скотный двор»

При написании своих классов желательно, чтобы семантика типичных операций была такой же, как у встроенных в Ruby классов. Например, если объекты класса можно упорядочивать, то имеет смысл реализовать метод

<=>
и подмешать модуль
Comparable
. Тогда к объектам вашего класса будут применимы все обычные операции сравнения.

Однако картина перестает быть такой однозначной, когда дело доходит до проверки объектов на равенство. В Ruby объекты реализуют пять разных методов

для этой операции. И в ваших классах придется реализовать хотя бы некоторые из них, поэтому рассмотрим этот вопрос подробнее.

Самым главным является метод

equal?
(унаследованный от класса
Object
); он возвращает
true
, если вызывающий объект и параметр имеют один и тот же идентификатор объекта. Это фундаментальный аспект семантики объектов, поэтому переопределять его не следует.

Самым распространенным способом проверки на равенство является старый добрый оператор

==
, который сравнивает значения вызывающего объекта и аргумента. Наверно, интуитивно это наиболее очевидный способ.

Следующим в шкале абстракции стоит метод

eql?
— тоже часть класса
Object
. (На самом деле метод
eql?
реализован в модуле
Kernel
, который подмешивается в
Object
.) Как и оператор
==
, этот метод сравнивает значения вызывающего объекта и аргумента, но несколько более строго. Например, разные числовые объекты при сравнении с помощью
==
приводятся к общему типу, но метод
eql?
никогда не считает объекты разных типов равными.

flag1 = (1 == 1.0) # true

flag2 = (1.eql?(1.0)) # false

Метод

eql?
существует по одной-единственной причине: для сравнения значений ключей хэширования. Если вы хотите переопределить стандартное поведение Ruby при использовании объектов в качестве ключей хэша, то переопределите методы
eql?
и
hash
.

Любой объект реализует еще два метода сравнения. Метод

===
применяется для сравнения проверяемого значения в предложении
case
с каждым селектором:
selector===target
. Хотя правило на первый взгляд кажется сложным, на практике оно делает предложения
case
в Ruby интуитивно очевидными. Например, можно выполнить ветвление по классу объекта:

case an_object

 when String

puts "Это строка."

 when Numeric

puts "Это число."

 else

puts "Это что-то совсем другое."

end

Эта конструкция работает, потому что в классе

Module
реализован метод
===
, проверяющий, принадлежит ли параметр тому же классу, что вызывающий объект (или одному из его предков). Поэтому, если
an_object
— это строка «cat», выражение
string === an_object
окажется истинным и будет выбрана первая ветвь в предложении
case
.

Наконец, в Ruby реализован оператор сопоставления с образцом

=~
.
Традиционно он применяется для сопоставления строки с регулярным выражением. Но если вы найдете ему применение в других классах, то можете переопределить.

У операторов

==
и
=~
есть противоположные формы:
!=
и
!~
соответственно. Внутри они реализованы путем обращения значения основной формы. Это означает, что если, например, вы реализовали метод
==
, то метод
!=
получаете задаром.

11.1.8. Управление доступом к методам

В Ruby объект определяется, прежде всего, своим интерфейсом: теми методами, которые он раскрывает внешнему миру. Но при написании класса часто возникает необходимость во вспомогательных методах, вызывать которые извне класса опасно. Тут-то и приходит на помощь метод

private
класса
Module
.

Использовать его можно двумя способами. Если в теле класса или модуля вы вызовете

private
без параметров, то все последующие методы будут закрытыми в данном классе или модуле. Если же вы передадите ему список имен методов (в виде символов), то эти и только эти методы станут закрытыми. В листинге 11.5 показаны оба варианта.

Листинг 11.5. Закрытые методы

class Bank

 def open_safe

# ...

 end

 def close_safe

# ...

 end

 private :open_safe, :close_safe

 def make_withdrawal(amount)

if access_allowed

open_safe

get_cash(amount)

close_safe

end

 end

 # Остальные методы закрытые.

private

 def get_cash

# ...

 end

 def access_allowed

# ...

 end

end

Поскольку методы из семейства

attr
просто определяют методы, метод
private
определяет и видимость атрибутов.

Реализация метода

private
может показаться странной, но на самом деле она весьма хитроумна. К закрытым методам нельзя обратиться, указав вызывающий объект; они вызываются только от имени неявно подразумеваемого объекта
self
. То есть вызвать закрытый метод из другого объекта не удастся: просто не существует способа указать объект, от имени которого данный метод вызывается. Заодно это означает, что закрытые методы доступны подклассам того класса, в котором определены, но опять же в рамках одного объекта.

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

Идеальный мир для Лекаря 10

Сапфир Олег
10. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 10

Эволюционер из трущоб. Том 4

Панарин Антон
4. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 4

Отмороженный

Гарцевич Евгений Александрович
1. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный

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

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

Идеальный мир для Лекаря 8

Сапфир Олег
8. Лекарь
Фантастика:
юмористическое фэнтези
аниме
7.00
рейтинг книги
Идеальный мир для Лекаря 8

На границе империй. Том 9. Часть 5

INDIGO
18. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 5

Черный Маг Императора 6

Герда Александр
6. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
7.00
рейтинг книги
Черный Маг Императора 6

Газлайтер. Том 17

Володин Григорий Григорьевич
17. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 17

Идеальный мир для Лекаря 6

Сапфир Олег
6. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 6

Газлайтер. Том 12

Володин Григорий Григорьевич
12. История Телепата
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 12

Древесный маг Орловского княжества 5

Павлов Игорь Васильевич
5. Орловское княжество
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Древесный маг Орловского княжества 5

Душелов. Том 6

Faded Emory
6. Внутренние демоны
Фантастика:
постапокалипсис
ранобэ
хентай
фэнтези
5.00
рейтинг книги
Душелов. Том 6

Прапорщик. Назад в СССР. Книга 6

Гаусс Максим
6. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прапорщик. Назад в СССР. Книга 6

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

Винокуров Юрий
38. Кодекс Охотника
Фантастика:
фэнтези
боевая фантастика
попаданцы
юмористическое фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XXXVIII