Я пытаюсь понять разницу между этими четырьмя методами. Я знаю по умолчанию, что ==
вызывает метод, equal?
который возвращает истину, когда оба операнда ссылаются на один и тот же объект.
===
по умолчанию также вызывает, ==
который вызывает equal?
... хорошо, так что, если все эти три метода не переопределены, то я думаю
===
, ==
и equal?
делать то же самое?
Сейчас приходит eql?
. Что это делает (по умолчанию)? Делает ли он вызов хеша / идентификатора операнда?
Почему в Ruby так много знаков равенства? Должны ли они отличаться по семантике?
ruby
comparison
operators
equality
Denniss
источник
источник
"a" == "a"
,"a" === "a"
и"a".eql? "a"
. Но это неверно:"a".equal? "a"
(Мой - ruby 1.9.2-p180)a = Object.new; b = Object.new
то все==
,===
,.equal?
,.eql?
вернусьtrue
кa
сравнениюa
и ложно дляa
противb
.Ответы:
Я собираюсь привести цитату из документации по объекту здесь, потому что я думаю, что она имеет несколько хороших объяснений. Я рекомендую вам прочитать его, а также документацию для этих методов, так как они переопределены в других классах, таких как String .
Примечание: если вы хотите попробовать их на разных объектах, используйте что-то вроде этого:
==
- общее "равенство"Это наиболее распространенное сравнение и, следовательно, самое фундаментальное место, где вы (как автор класса) можете решить, «равны» два объекта или нет.
===
- равенство случаевЭто невероятно полезно. Примеры вещей, которые имеют интересные
===
реализации:Таким образом, вы можете сделать такие вещи, как:
Посмотрите мой ответ здесь, чтобы получить хороший пример того, как
case
+Regex
может сделать код намного чище. И, конечно, предоставляя собственную===
реализацию, вы можете получить пользовательскуюcase
семантику.eql?
-Hash
равенствоТаким образом, вы можете переопределить это для своих собственных нужд, или вы можете переопределить
==
и использоватьalias :eql? :==
так, чтобы оба метода вели себя одинаково.equal?
- сравнение личностиЭто эффективное сравнение указателей.
источник
Numeric
оно обрабатывается более строго, чем==
. Это действительно зависит от автора класса.===
редко используется внеcase
утверждений.===
значении "спички" (примерно). Например, «совпадает ли регулярное выражение со строкой» или «соответствует ли диапазон (включает) число».Мне нравится ответ jtbandes, но так как он довольно длинный, я добавлю свой компактный ответ:
==
,===
,eql?
,equal?
4 компараторов, то есть. 4 способа сравнить 2 объекта, в Ruby.
Поскольку в Ruby все компараторы (и большинство операторов) фактически являются вызовами методов, вы можете изменить, перезаписать и определить семантику этих методов сравнения самостоятельно. Однако важно понимать, когда внутренние языковые конструкции Ruby используют компаратор:
==
(сравнение значений)Ruby везде использует: == для сравнения значений двух объектов, например. Хэш-значения:
===
(сравнение случаев)Ruby использует: === в случае / когда конструкции. Следующие фрагменты кода логически идентичны:
eql?
(Сравнение хэш-ключей)Ruby использует: eql? (в сочетании с методом hash) для сравнения Hash-ключей. В большинстве классов: eql? совпадает с: ==.
Знание о: eql? важно только тогда, когда вы хотите создать свои собственные специальные классы:
Примечание. Обычно используемый набор Ruby-класса также основан на сравнении хэш-ключей.
equal?
(сравнение идентичности объекта)Ruby использует: равно? проверить, идентичны ли два объекта. Этот метод (класса BasicObject) не должен быть перезаписан.
источник
eql?
очень вводит в заблуждение.eql?
это сравнение на равенство, которое согласуется с тем, как вычисляется хеш, т.е.a.eql?(b)
гарантирует этоa.hash == b.hash
. Он не просто сравнивает хеш-коды.bar === foo
и нетfoo === bar
? Я надеюсь, что последнее правильно и важно, так как компилятор вызывает левую часть: === `'bar === foo
: Ruby использует значение case в левой части и переменную case в правой части. Это может быть связано с избеганием NPE (исключения нулевого указателя).Операторы равенства: == и! =
Оператор ==, также известный как равенство или двойное равенство, вернет true, если оба объекта равны, и false, если это не так.
Оператор! =, Также известный как неравенство, является противоположностью ==. Он вернет истину, если оба объекта не равны, и ложь, если они равны.
Обратите внимание, что два массива с одинаковыми элементами в разном порядке не равны, прописные и строчные версии одной и той же буквы не равны и так далее.
При сравнении чисел разных типов (например, целых и чисел с плавающей точкой), если их числовые значения одинаковы, == вернет true.
равны?
В отличие от оператора ==, который проверяет, равны ли оба операнда, метод равенства проверяет, ссылаются ли два операнда на один и тот же объект. Это самая строгая форма равенства в Ruby.
Пример: a = "zen" b = "zen"
В приведенном выше примере у нас есть две строки с одинаковым значением. Однако это два разных объекта с разными идентификаторами объектов. Значит, равный? метод вернет false.
Попробуем еще раз, только на этот раз b будет ссылкой на a. Обратите внимание, что идентификатор объекта одинаков для обеих переменных, так как они указывают на один и тот же объект.
EQL?
В классе Hash, eql? Метод используется для проверки ключей на равенство. Некоторый фон требуется, чтобы объяснить это. В общем контексте вычислений хеш-функция берет строку (или файл) любого размера и генерирует строку или целое число фиксированного размера, называемое хеш-кодом, обычно называемое только хеш-кодом. Некоторые часто используемые типы хеш-кодов: MD5, SHA-1 и CRC. Они используются в алгоритмах шифрования, индексации базы данных, проверке целостности файлов и т. Д. Некоторые языки программирования, такие как Ruby, предоставляют тип коллекции, называемый хэш-таблицей. Хеш-таблицы - это словарные коллекции, в которых данные хранятся парами, состоящими из уникальных ключей и соответствующих им значений. Под капотом эти ключи хранятся в виде хэш-кодов. Хеш-таблицы обычно называют просто хешами. Обратите внимание, как слово hash может относиться к хеш-коду или хеш-таблице.
Ruby предоставляет встроенный метод hash для генерации хеш-кодов. В приведенном ниже примере он принимает строку и возвращает хеш-код. Обратите внимание, что строки с одинаковым значением всегда имеют одинаковый хеш-код, даже если они являются разными объектами (с разными идентификаторами объектов).
Хеш-метод реализован в модуле Kernel, включенном в класс Object, который является корнем по умолчанию для всех объектов Ruby. Некоторые классы, такие как Symbol и Integer, используют реализацию по умолчанию, другие, такие как String и Hash, предоставляют свои собственные реализации.
В Ruby, когда мы храним что-то в хеше (коллекции), объект, предоставленный как ключ (например, строка или символ), преобразуется в и сохраняется как хеш-код. Позже, извлекая элемент из хеша (коллекции), мы предоставляем объект в качестве ключа, который преобразуется в хеш-код и сравнивается с существующими ключами. Если есть совпадение, возвращается значение соответствующего элемента. Сравнение сделано с помощью EQL? метод под капотом.
В большинстве случаев, eql? Метод ведет себя аналогично методу ==. Однако есть несколько исключений. Например, eql? не выполняет неявное преобразование типов при сравнении целого числа с плавающей точкой.
Оператор равенства случая: ===
Многие встроенные в Ruby классы, такие как String, Range и Regexp, предоставляют свои собственные реализации оператора ===, также известного как case-равенства, тройного равенства или тройного равенства. Поскольку он реализован по-разному в каждом классе, он будет вести себя по-разному в зависимости от типа объекта, к которому он был вызван. Как правило, он возвращает true, если объект справа «принадлежит» или «является членом» объекта слева. Например, его можно использовать для проверки того, является ли объект экземпляром класса (или одним из его подклассов).
Тот же результат может быть достигнут с помощью других методов, которые, вероятно, лучше всего подходят для работы. Как правило, лучше писать код, который легко читать, будучи максимально явным, не жертвуя эффективностью и краткостью.
Обратите внимание, что последний пример вернул false, поскольку целые числа, такие как 2, являются экземплярами класса Fixnum, который является подклассом класса Integer. ===, is_a? и instance_of? методы возвращают true, если объект является экземпляром данного класса или любых подклассов. Метод instance_of является более строгим и возвращает true, только если объект является экземпляром этого точного класса, а не подклассом.
Is_a? и добрый_? методы реализованы в модуле Kernel, который смешивается с классом Object. Оба являются псевдонимами одного и того же метода. Давайте проверим:
Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Выход: => true
Диапазон реализации ===
Когда оператор === вызывается для объекта диапазона, он возвращает true, если значение справа попадает в диапазон слева.
Помните, что оператор === вызывает метод === левого объекта. Итак, (1..4) === 3 эквивалентно (1..4). === 3. Другими словами, класс левого операнда определит, какая реализация метода === будет называется, так что позиции операндов не являются взаимозаменяемыми.
Regexp Реализация ===
Возвращает true, если строка справа соответствует регулярному выражению слева. / zen / === "тренируйся дзадзэн сегодня" # Вывод: => true # - то же самое, что и "тренируйся дзадзэн сегодня" = ~ / zen /
Неявное использование оператора === в операторах case / when
Этот оператор также используется под оператором case / when. Это его наиболее распространенное использование.
В приведенном выше примере, если в Ruby неявно использовался оператор двойного равенства (==), диапазон 10..20 не будет считаться равным целому числу, например 15. Они совпадают, поскольку оператор тройного равенства (===) неявно используется во всех случаях / когда заявления. Код в приведенном выше примере эквивалентен:
Операторы сопоставления с образцом: = ~ и! ~
Операторы = ~ (equal-tilde) и! ~ (Bang-tilde) используются для сопоставления строк и символов с шаблонами регулярных выражений.
Реализация метода = ~ в классах String и Symbol предполагает регулярное выражение (экземпляр класса Regexp) в качестве аргумента.
Реализация в классе Regexp ожидает строку или символ в качестве аргумента.
Во всех реализациях, когда строка или символ соответствуют шаблону Regexp, он возвращает целое число, которое является позицией (индексом) соответствия. Если совпадений нет, возвращается ноль. Помните, что в Ruby любое целочисленное значение является «правдивым», а nil - «ложным», поэтому оператор = ~ можно использовать в операторах if и троичных операторах.
Операторы сопоставления с образцом также полезны для написания более коротких операторов if. Пример:
Оператор! ~ Противоположен = ~, он возвращает истину, если совпадения нет, и ложь, если совпадение есть.
Более подробная информация доступна в этом блоге .
источник
:zen === "zen"
возвращается falseRuby предоставляет несколько различных методов обработки равенства:
Продолжите чтение, нажав на ссылку ниже, это дало мне ясное обобщенное понимание.
Надеюсь, что это помогает другим.
источник
=== # --- регистр равенства
== # --- общее равенство
оба работают одинаково, но "===" даже делают заявления случая
здесь разница
источник
a==b
тогдаa===b
. Ноa===b
гораздо мощнее.===
не является симметричным, иa===b
означает совсем другую вещьb===a
, не говоря уже оa==b
.Я хотел бы расширить на
===
оператора.===
не является оператором равенства!Не.
Давайте выясним это на самом деле.
Вы можете быть знакомы с
===
оператором равенства в Javascript и PHP, но это просто не оператор равенства в Ruby и имеет принципиально другую семантику.Так что же
===
делать?===
оператор сопоставления с шаблоном!===
соответствует регулярным выражениям===
проверяет членство в диапазоне===
проверяет наличие экземпляра класса===
вызывает лямбда-выражения===
иногда проверяет равенство, но в основном это не такТак как же это безумие имеет смысл?
Enumerable#grep
использует===
внутреннеcase when
заявления используют===
внутриrescue
использует===
внутреннеВот почему вы можете использовать регулярные выражения и классы и диапазоны и даже лямбда-выражения в
case when
выражении.Некоторые примеры
Все эти примеры работают
pattern === value
как сgrep
методом , так и с ним .источник
Я написал простой тест для всего вышеперечисленного.
источник