Próbuję zrozumieć różnicę między tymi czterema metodami. Wiem, że domyślnie ==
wywołuje metodę, equal?
która zwraca true, gdy oba operandy odnoszą się do dokładnie tego samego obiektu.
===
domyślnie także wywołuje ==
które połączenia equal?
... dobrze, więc jeśli wszystkie te trzy metody nie zostaną zastąpione, to myślę ===
, że
==
i equal?
robię dokładnie to samo?
Teraz nadchodzi eql?
. Co to robi (domyślnie)? Czy wywołuje skrót / identyfikator operandu?
Dlaczego Ruby ma tyle znaków równości? Czy mają się różnić semantyką?
ruby
comparison
operators
equality
denniss
źródło
źródło
"a" == "a"
,"a" === "a"
i"a".eql? "a"
. Ale to nieprawda:"a".equal? "a"
(Mój jest rubinowy 1.9.2-p180)a = Object.new; b = Object.new
wtedy wszystko==
,===
,.equal?
,.eql?
powrócitrue
doa
vsa
false dlaa
vsb
.Odpowiedzi:
Zamierzam zacytować tutaj dokumentację Object , ponieważ myślę, że zawiera ona kilka świetnych wyjaśnień. Zachęcam do przeczytania go, a także dokumentacji tych metod, ponieważ są one zastępowane w innych klasach, takich jak String .
Uwaga dodatkowa: jeśli chcesz je wypróbować na różnych obiektach, użyj czegoś takiego:
==
- ogólna „równość”Jest to najczęstsze porównanie, a zatem najbardziej fundamentalne miejsce, w którym (jako autor klasy) decydujesz, czy dwa obiekty są „równe”, czy nie.
===
- równość wielkości literJest to niezwykle przydatne. Przykłady rzeczy, które mają ciekawe
===
implementacje:Możesz więc robić takie rzeczy jak:
Zobacz moją odpowiedź tutaj, aby znaleźć dobry przykład tego, jak
case
+Regex
może uczynić kod o wiele czystszym. Oczywiście, udostępniając własną===
implementację, można uzyskać niestandardowącase
semantykę.eql?
-Hash
równośćMożesz więc zastąpić to dla własnych celów lub możesz zastąpić
==
i użyć,alias :eql? :==
aby obie metody zachowywały się w ten sam sposób.equal?
- porównanie tożsamościJest to efektywne porównanie wskaźników.
źródło
Numeric
traktuje się go bardziej rygorystycznie niż==
. To naprawdę zależy od autora klasy.===
jest rzadko używany pozacase
instrukcjami.===
oznacza „mecze” (z grubsza). Jak w „czy wyrażenie regularne pasuje do ciągu” lub „czy zakres odpowiada (obejmuje) liczbę”.Uwielbiam odpowiedź jtbandes, ale ponieważ jest dość długa, dodam własną kompaktową odpowiedź:
==
,===
,eql?
,equal?
Są 4 komparatory, tj. 4 sposoby porównywania 2 obiektów w Ruby.
Ponieważ w Ruby wszystkie komparatory (i większość operatorów) są w rzeczywistości wywołaniami metod, możesz sam zmienić, zastąpić i zdefiniować semantykę tych metod porównywania. Jednak ważne jest, aby zrozumieć, kiedy konstrukcje języka wewnętrznego Ruby używają tego komparatora:
==
(porównanie wartości)Ruby używa: == wszędzie, aby porównać wartości 2 obiektów, np. Wartości skrótu:
===
(porównanie wielkości liter)Ruby używa: === w przypadku / kiedy konstruuje. Następujące fragmenty kodu są logicznie identyczne:
eql?
(Porównanie klucza skrótu)Używa Ruby: eql? (w połączeniu z skrótem metody), aby porównać klucze skrótu. W większości klas: eql? jest identyczny z: ==.
Wiedza na temat: eql? jest ważne tylko wtedy, gdy chcesz stworzyć własne klasy specjalne:
Uwaga: Powszechnie używany zestaw klasy Ruby opiera się również na porównaniu klucza skrótu.
equal?
(porównanie tożsamości obiektu)Używa Ruby: równy? aby sprawdzić, czy dwa obiekty są identyczne. Ta metoda (klasy BasicObject) nie powinna zostać nadpisana.
źródło
eql?
jest bardzo mylący.eql?
to porównanie równości, które jest spójne ze sposobem obliczania wartości skrótu, tzn.a.eql?(b)
gwarantuje toa.hash == b.hash
. To nie nie po prostu porównać kody hash.bar === foo
czy niefoo === bar
? Mam nadzieję, że to drugie jest poprawne i jest ważne, ponieważ kompilator wywołuje lewą stronę: === ``bar === foo
Ruby używa wartości wielkości liter po lewej stronie i zmiennej wielkości liter po prawej stronie. Może to mieć związek z unikaniem NPE (wyjątki zerowego wskaźnika).Operatory równości: == i! =
Operator ==, znany również jako równość lub podwójna równość, zwróci true, jeśli oba obiekty są równe, a false, jeśli nie są.
Operator! =, Znany również jako nierówność, jest przeciwieństwem ==. Zwróci wartość true, jeśli oba obiekty nie są równe, i false, jeśli są równe.
Zauważ, że dwie tablice z tymi samymi elementami w innej kolejności nie są równe, wielkie i małe wersje tej samej litery nie są równe i tak dalej.
Podczas porównywania liczb różnych typów (np. Liczba całkowita i liczba zmiennoprzecinkowa), jeśli ich wartość liczbowa jest taka sama, == zwróci wartość true.
równy?
W przeciwieństwie do operatora ==, który sprawdza, czy oba argumenty są równe, metoda równości sprawdza, czy dwa argumenty odnoszą się do tego samego obiektu. Jest to najostrzejsza forma równości w Rubim.
Przykład: a = „zen” b = „zen”
W powyższym przykładzie mamy dwa ciągi o tej samej wartości. Są to jednak dwa odrębne obiekty o różnych identyfikatorach obiektów. Stąd równy? metoda zwróci false.
Spróbujmy jeszcze raz, tylko tym razem b będzie odniesieniem do a. Zauważ, że identyfikator obiektu jest taki sam dla obu zmiennych, ponieważ wskazują one na ten sam obiekt.
eql?
W klasie Hash eql? metoda służy do testowania kluczy pod kątem równości. Aby to wyjaśnić, wymagane jest pewne doświadczenie. W ogólnym kontekście obliczeń funkcja skrótu pobiera ciąg (lub plik) o dowolnym rozmiarze i generuje ciąg lub liczbę całkowitą o stałym rozmiarze, zwaną hashcode, zwaną zwykle hashem. Niektóre powszechnie używane typy skrótów to MD5, SHA-1 i CRC. Są one używane w algorytmach szyfrowania, indeksowaniu baz danych, sprawdzaniu integralności plików itp. Niektóre języki programowania, takie jak Ruby, zapewniają typ kolekcji zwany tablicą skrótów. Tabele skrótów są kolekcjami przypominającymi słownik, które przechowują dane w parach, składające się z unikalnych kluczy i odpowiadających im wartości. Pod maską te klucze są przechowywane jako kody skrótu. Tabele skrótów są powszechnie nazywane skrótami. Zauważ, jak słowo hashcan może odnosić się do hashcode lub do tablicy hash.
Ruby zapewnia wbudowaną metodę zwaną hash do generowania skrótów. W poniższym przykładzie pobiera ciąg znaków i zwraca kod skrótu. Zauważ, że ciągi o tej samej wartości zawsze mają ten sam kod skrótu, nawet jeśli są odrębnymi obiektami (o różnych identyfikatorach obiektów).
Metoda skrótu jest zaimplementowana w module jądra, zawartym w klasie Object, która jest domyślnym katalogiem głównym wszystkich obiektów Ruby. Niektóre klasy, takie jak Symbol i Integer, używają domyślnej implementacji, inne jak String i Hash zapewniają własne implementacje.
W Ruby, kiedy przechowujemy coś w haszu (kolekcji), obiekt podany jako klucz (np. Łańcuch lub symbol) jest konwertowany i zapisywany jako kod skrótu. Później, podczas pobierania elementu z skrótu (kolekcji), udostępniamy obiekt jako klucz, który jest konwertowany na kod skrótu i porównywany z istniejącymi kluczami. Jeśli istnieje dopasowanie, zwracana jest wartość odpowiedniego elementu. Porównanie odbywa się za pomocą eql? metoda pod maską.
W większości przypadków eql? Metoda zachowuje się podobnie do metody ==. Jest jednak kilka wyjątków. Na przykład eql? nie wykonuje niejawnej konwersji typu podczas porównywania liczby całkowitej z liczbą zmiennoprzecinkową.
Operator równości wielkości: ===
Wiele wbudowanych klas Ruby, takich jak String, Range i Regexp, zapewnia własne implementacje operatora ===, znanego również jako równość wielkości liter, potrójne równe lub trzykwale. Ponieważ jest zaimplementowany inaczej w każdej klasie, będzie zachowywać się inaczej w zależności od typu obiektu, do którego został wywołany. Zasadniczo zwraca wartość true, jeśli obiekt po prawej „należy do” lub „jest członkiem” obiektu po lewej stronie. Na przykład można go użyć do przetestowania, czy obiekt jest instancją klasy (lub jednej z jej podklas).
Ten sam wynik można osiągnąć za pomocą innych metod, które prawdopodobnie najlepiej nadają się do pracy. Zwykle lepiej jest napisać kod, który jest łatwy do odczytania, tak wyraźny, jak to możliwe, bez poświęcania wydajności i zwięzłości.
Zwróć uwagę, że ostatni przykład zwrócił wartość false, ponieważ liczby całkowite, takie jak 2, są instancjami klasy Fixnum, która jest podklasą klasy Integer. ===, is_a? i instance_of? metody zwracają wartość true, jeśli obiekt jest instancją danej klasy lub dowolnej podklasy. Metoda instance_of jest bardziej rygorystyczna i zwraca true tylko wtedy, gdy obiekt jest instancją tej właśnie klasy, a nie podklasą.
Czy to jest? i rodzaj? metody są zaimplementowane w module jądra, który jest mieszany przez klasę Object. Oba są pseudonimami tej samej metody. Sprawdźmy:
Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Output: => true
Zakres realizacji ===
Gdy operator === jest wywoływany na obiekcie zakresu, zwraca wartość true, jeśli wartość po prawej stronie mieści się w zakresie po lewej stronie.
Pamiętaj, że operator === wywołuje metodę === obiektu po lewej stronie. Więc (1..4) === 3 jest równoważne z (1..4). === 3. Innymi słowy, klasa operandu po lewej stronie określi, która implementacja metody === będzie wywołane, więc pozycje operandu nie są zamienne.
Implementacja Regexp ===
Zwraca true, jeśli ciąg po prawej stronie pasuje do wyrażenia regularnego po lewej. / zen / === „ćwiczenie zazen dzisiaj” # Wyjście: => true # to to samo co „ćwiczenie zazen dzisiaj” = ~ / zen /
Niejawne użycie operatora === w instrukcjach case / when
Ten operator jest również używany pod maską na instrukcjach dotyczących przypadków / kiedy. To jest jego najczęstsze zastosowanie.
W powyższym przykładzie, gdyby Ruby domyślnie zastosowała operator podwójnej równości (==), zakres 10..20 nie byłby uważany za równy liczbie całkowitej, takiej jak 15. Pasują, ponieważ potrójny operator równości (===) to domyślnie używane we wszystkich instrukcjach case / when. Kod w powyższym przykładzie jest równoważny z:
Operatory dopasowywania wzorców: = ~ i! ~
Operatory = ~ (równa tylda) i! ~ (Bang-tylda) służą do dopasowania ciągów i symboli do wzorców wyrażeń regularnych.
Implementacja metody = ~ w klasach String i Symbol oczekuje wyrażenia regularnego (instancji klasy Regexp) jako argumentu.
Implementacja w klasie Regexp oczekuje ciągu lub symbolu jako argumentu.
We wszystkich implementacjach, gdy ciąg lub symbol pasuje do wzorca Regexp, zwraca liczbę całkowitą, która jest pozycją (indeksem) dopasowania. Jeśli nie ma dopasowania, zwraca zero. Pamiętaj, że w Rubim każda wartość całkowita jest „prawda”, a zero to „fałsz”, więc operator = ~ może być użyty w instrukcjach if i operatorach trójskładnikowych.
Operatory dopasowywania wzorców są również przydatne do pisania krótszych instrukcji if. Przykład:
Operator! ~ Jest przeciwieństwem = ~, zwraca true, gdy nie ma dopasowania, i false, jeśli istnieje dopasowanie.
Więcej informacji jest dostępnych w tym poście na blogu .
źródło
:zen === "zen"
zwraca falseRuby przedstawia kilka różnych metod postępowania z równością:
Kontynuuj czytanie, klikając poniższy link, co dało mi jasne podsumowanie.
Mam nadzieję, że pomaga innym.
źródło
=== # --- równość wielkości liter
== # --- ogólna równość
oba działają podobnie, ale „===” nawet wykonuje instrukcje case
tutaj różnica
źródło
a==b
potema===b
. Alea===b
jest znacznie potężniejszy.===
nie jest symetryczny ia===b
oznacza coś zupełnie innego niżb===a
, nie mówiąc już o tyma==b
.Chciałbym rozwinąć
===
operatora.===
nie jest operatorem równości!Nie.
Przejdźmy do tego punktu naprawdę.
Być może znasz się
===
jako operator równości w JavaScript i PHP, ale to po prostu nie jest operator równości w Ruby i ma zasadniczo inną semantykę.Co więc robi
===
?===
jest operatorem dopasowywania wzorców!===
dopasowuje wyrażenia regularne===
sprawdza członkostwo w zakresie===
sprawdza, czy jest instancją klasy===
wywołuje wyrażenia lambda===
czasami sprawdza równość, ale przeważnie nieWięc jak to szaleństwo ma sens?
Enumerable#grep
wykorzystuje===
wewnętrzniecase when
używać instrukcji===
wewnętrznierescue
wykorzystuje===
wewnętrznieDlatego możesz używać wyrażeń regularnych oraz klas i zakresów, a nawet wyrażeń lambda w
case when
.Kilka przykładów
Wszystkie te przykłady
pattern === value
również działają zgrep
metodami.źródło
Napisałem prosty test na wszystkie powyższe.
źródło