11.1.7. Проверка объектов на равенство
11.1.7. Проверка объектов на равенство
Все животные равны, но некоторые равнее других.
Джордж Оруэлл, «Скотный двор»
При написании своих классов желательно, чтобы семантика типичных операций была такой же, как у встроенных в 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 реализован оператор сопоставления с образцом =~. Традиционно он применяется для сопоставления строки с регулярным выражением. Но если вы найдете ему применение в других классах, то можете переопределить.
У операторов == и =~ есть противоположные формы: != и !~ соответственно. Внутри они реализованы путем обращения значения основной формы. Это означает, что если, например, вы реализовали метод ==, то метод != получаете задаром.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Защита объектов ядра и приватных объектов
Защита объектов ядра и приватных объектов Многие объекты, такие как процессы, потоки или мьютексы, являются объектами ядра (kernel objects). Для получения и установки дескрипторов безопасности ядра используются функции GetKernelObjectsSecurity и SetKernelObjectsSecurity, аналогичные функциям защиты
Проверка
Проверка Установка цветов в соответствии с правилами может здорово помочь при проверке данных на этапе ввода. Например, аварийным красным будут выделяться значения, явно выходящие за рамки указанного диапазона, или подсвечиваться желтым «подозрительные» слова и цифры.
Проверка диска
Проверка диска Ошибки, возникающие на жестком диске, можно условно разделить на два типа: аппаратные и программные. Аппаратные связаны с механическим повреждением магнитного слоя диска в некоторых секторах, в результате чего они становятся непригодными для записи и
Проверка ссылок
Проверка ссылок До начала рекламной кампании стоит убедиться в том, что в текстах страниц, размещенных на сайте, нет технических ошибок. К таковым относятся неправильно расставленные ссылки, отсутствие каких-либо файлов и собственно погрешности в HTML-коде, а также
Проверка правописания
Проверка правописания Пользователи не любят опечаток и грамматических ошибок и из-за них могут отказаться от посещения вашего сайта. Если вас плохо владеете орфографией и пунктуацией, попросите кого-нибудь сведущего проверить правописание текста, либо воспользуйтесь
R.5.10 Операции сравнения на равенство
R.5.10 Операции сравнения на равенство выражение-равенства: выражение-отношения выражение-равенства == выражение-отношения выражение-равенства != выражение-отношенияОперации == (равно) и != (не равно) аналогичны операциям отношения, за исключением того, что их приоритет
Проверка правописания
Проверка правописания Несмотря на совсем крошечный объем, программа RoughDraft содержит собственный словарь для проверки правописания. К сожалению, тестируемый нами образец не содержал русского словаря (возможно, в дальнейшем словарь программы будет им дополнен). Однако
Автоматическая проверка
Автоматическая проверка При автоматическом контроле орфографии и грамматики Word проверяет в тексте ошибки непосредственно при наборе. В таком случае сразу после того, как слово или предложение набрано, видно, допущена ошибка или нет: программа подчеркивает слова,
Проверка
Проверка Так ли уж правильны наши рассуждения? Давайте проверим нашу функцию на учебной программе:/* проверка функции getint( )*/#define STOP - 1#define NONUM 1#define YESNUM 0main( ){int num, status;printf(" Программа прекращает считывание чисел, если встречает EOF. " );while((status = getint(&num)) != STOP)if(status = =
Сравнение на равенство (Equal)
Сравнение на равенство (Equal) template ‹class InputIterator1, class InputIterator2›bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2);template ‹class InputIterator1, class InputIterator2, class BinaryPredicate›bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate binary_pred);equal возвращает true, если для каждого итератора i в диапазоне [first1, last1)
Проверка
Проверка Инструкция проверки рассматривалась при обсуждении утверждений (лекция 11). Она говорит, что определенные утверждения должны удовлетворяться в определенных точках:checkassertion -- Одно или больше