Ich versuche den Unterschied zwischen diesen vier Methoden zu verstehen. Ich weiß standardmäßig, dass ==
die Methode equal?
aufgerufen wird, die true zurückgibt, wenn beide Operanden auf genau dasselbe Objekt verweisen.
===
Standardmäßig werden auch ==
welche Aufrufe equal?
aufgerufen ... okay, wenn also alle drei Methoden nicht überschrieben werden, dann denke ich
===
, ==
und equal?
genau das Gleiche tun?
Jetzt kommt eql?
. Was macht das (standardmäßig)? Ruft es den Hash / die ID des Operanden auf?
Warum hat Ruby so viele Gleichheitszeichen? Sollen sie sich in der Semantik unterscheiden?
ruby
comparison
operators
equality
denniss
quelle
quelle
"a" == "a"
,"a" === "a"
und"a".eql? "a"
. Aber das ist falsch:"a".equal? "a"
(Meins ist Rubin 1.9.2-p180)a = Object.new; b = Object.new
allen dann==
,===
,.equal?
,.eql?
kehrttrue
füra
vsa
und falsch füra
vsb
.Antworten:
Ich werde die Objektdokumentation hier ausführlich zitieren , da ich denke, dass sie einige großartige Erklärungen enthält. Ich empfehle Ihnen, es und auch die Dokumentation für diese Methoden zu lesen, da sie in anderen Klassen wie String überschrieben werden .
Randnotiz: Wenn Sie diese an verschiedenen Objekten selbst ausprobieren möchten, verwenden Sie Folgendes:
==
- generische "Gleichheit"Dies ist der häufigste Vergleich und damit der grundlegendste Ort, an dem Sie (als Autor einer Klasse) entscheiden können, ob zwei Objekte "gleich" sind oder nicht.
===
- FallgleichheitDas ist unglaublich nützlich. Beispiele für Dinge, die interessante
===
Implementierungen haben:So können Sie Dinge tun wie:
In meiner Antwort hier finden Sie ein gutes Beispiel dafür, wie
case
+Regex
Code viel sauberer machen kann. Und natürlich können Sie durch die Bereitstellung Ihrer eigenen===
Implementierung eine benutzerdefiniertecase
Semantik erhalten.eql?
-Hash
GleichheitSie können dies also für Ihre eigenen
==
Zwecke überschreiben, oder Sie können es überschreiben und verwenden,alias :eql? :==
damit sich die beiden Methoden gleich verhalten.equal?
- IdentitätsvergleichDies ist effektiv ein Zeigervergleich.
quelle
Numeric
er strenger behandelt wird als==
. Es liegt wirklich am Autor der Klasse.===
wird nur selten außerhalb voncase
Anweisungen verwendet.===
"Übereinstimmungen" bedeutet (ungefähr). Wie in "Stimmt der reguläre Ausdruck mit der Zeichenfolge überein" oder "Stimmt der Bereich mit der Zahl überein (schließt sie ein)".Ich liebe jtbandes Antwort, aber da es ziemlich lang ist, werde ich meine eigene kompakte Antwort hinzufügen:
==
,===
,eql?
,equal?
Sind 4 Komparatoren, dh. 4 Möglichkeiten, 2 Objekte in Ruby zu vergleichen.
Da in Ruby alle Komparatoren (und die meisten Operatoren) tatsächlich Methodenaufrufe sind, können Sie die Semantik dieser Vergleichsmethoden selbst ändern, überschreiben und definieren. Es ist jedoch wichtig zu verstehen, wann Rubys interne Sprachkonstrukte welchen Komparator verwenden:
==
(Wertevergleich)Ruby verwendet: == überall, um die Werte von 2 Objekten zu vergleichen , z. Hash-Werte:
===
(Fallvergleich ) Ruby verwendet: === in case / when-Konstrukten. Die folgenden Codefragmente sind logisch identisch:
eql?
(Hash-Key-Vergleich)Ruby verwendet: eql? (in Kombination mit dem Methoden-Hash) zum Vergleichen von Hash-Schlüsseln. In den meisten Klassen: Gl. ist identisch mit: ==.
Wissen über: eql? ist nur wichtig, wenn Sie Ihre eigenen speziellen Klassen erstellen möchten:
Hinweis: Das häufig verwendete Ruby-Klassen-Set basiert auch auf einem Hash-Schlüssel-Vergleich.
equal?
(Objektidentitätsvergleich)Ruby verwendet: gleich? um zu überprüfen, ob zwei Objekte identisch sind. Diese Methode (der Klasse BasicObject) darf nicht überschrieben werden.
quelle
eql?
ist sehr irreführend.eql?
ist ein Gleichheitsvergleich, der mit der Berechnung des Hash übereinstimmt , dh diesa.eql?(b)
garantierta.hash == b.hash
. Es werden nicht einfach die Hash-Codes verglichen.bar === foo
und nichtfoo === bar
? Ich würde hoffen, dass Letzteres korrekt ist und es wichtig ist, da der Compiler die linke Seite aufruft: === `'bar === foo
: Ruby verwendet den Fallwert auf der linken Seite und die Fallvariable auf der rechten Seite. Dies hat möglicherweise mit der Vermeidung von NPEs (Null Pointer Exceptions) zu tun.Gleichheitsoperatoren: == und! =
Der Operator ==, auch als Gleichheit oder Doppelgleichheit bezeichnet, gibt true zurück, wenn beide Objekte gleich sind, und false, wenn dies nicht der Fall ist.
Der Operator! =, Auch als Ungleichung bekannt, ist das Gegenteil von ==. Es wird true zurückgegeben, wenn beide Objekte nicht gleich sind, und false, wenn sie gleich sind.
Beachten Sie, dass zwei Arrays mit denselben Elementen in einer anderen Reihenfolge nicht gleich sind, Groß- und Kleinbuchstaben desselben Buchstabens nicht gleich sind und so weiter.
Wenn beim Vergleichen von Zahlen verschiedener Typen (z. B. Integer und Float) der numerische Wert gleich ist, gibt == true zurück.
gleich?
Im Gegensatz zum Operator ==, der prüft, ob beide Operanden gleich sind, prüft die Methode same, ob sich die beiden Operanden auf dasselbe Objekt beziehen. Dies ist die strengste Form der Gleichheit in Ruby.
Beispiel: a = "Zen" b = "Zen"
Im obigen Beispiel haben wir zwei Zeichenfolgen mit demselben Wert. Es handelt sich jedoch um zwei unterschiedliche Objekte mit unterschiedlichen Objekt-IDs. Daher ist das gleiche? Methode gibt false zurück.
Versuchen wir es noch einmal, nur dieses Mal wird b ein Verweis auf a sein. Beachten Sie, dass die Objekt-ID für beide Variablen gleich ist, da sie auf dasselbe Objekt verweisen.
Äql?
In der Hash-Klasse ist die Gl. Methode wird verwendet, um Schlüssel auf Gleichheit zu testen. Einige Hintergrundinformationen sind erforderlich, um dies zu erklären. Im allgemeinen Kontext des Rechnens nimmt eine Hash-Funktion eine Zeichenfolge (oder eine Datei) beliebiger Größe und generiert eine Zeichenfolge oder Ganzzahl fester Größe, die als Hashcode bezeichnet wird und üblicherweise nur als Hash bezeichnet wird. Einige häufig verwendete Hashcode-Typen sind MD5, SHA-1 und CRC. Sie werden in Verschlüsselungsalgorithmen, bei der Datenbankindizierung, bei der Überprüfung der Dateiintegrität usw. verwendet. Einige Programmiersprachen, wie z. B. Ruby, bieten einen Sammlungstyp namens Hash-Tabelle. Hash-Tabellen sind wörterbuchartige Sammlungen, die Daten paarweise speichern und aus eindeutigen Schlüsseln und ihren entsprechenden Werten bestehen. Unter der Haube werden diese Schlüssel als Hashcodes gespeichert. Hash-Tabellen werden üblicherweise nur als Hashes bezeichnet. Beachten Sie, wie sich das Wort Hash auf einen Hashcode oder eine Hash-Tabelle beziehen kann.
Ruby bietet eine integrierte Methode namens Hash zum Generieren von Hashcodes. Im folgenden Beispiel wird eine Zeichenfolge verwendet und ein Hashcode zurückgegeben. Beachten Sie, dass Zeichenfolgen mit demselben Wert immer denselben Hashcode haben, obwohl es sich um unterschiedliche Objekte handelt (mit unterschiedlichen Objekt-IDs).
Die Hash-Methode ist im Kernel-Modul implementiert, das in der Object-Klasse enthalten ist. Dies ist das Standardstammverzeichnis aller Ruby-Objekte. Einige Klassen wie Symbol und Integer verwenden die Standardimplementierung, andere wie String und Hash stellen ihre eigenen Implementierungen bereit.
Wenn wir in Ruby etwas in einem Hash (einer Sammlung) speichern, wird das als Schlüssel bereitgestellte Objekt (z. B. Zeichenfolge oder Symbol) in einen Hashcode konvertiert und als Hashcode gespeichert. Wenn wir später ein Element aus dem Hash (Sammlung) abrufen, stellen wir ein Objekt als Schlüssel bereit, das in einen Hashcode konvertiert und mit den vorhandenen Schlüsseln verglichen wird. Wenn eine Übereinstimmung vorliegt, wird der Wert des entsprechenden Elements zurückgegeben. Der Vergleich erfolgt mit der Gleichung? Methode unter der Haube.
In den meisten Fällen ist die Gl. Methode verhält sich ähnlich wie die == Methode. Es gibt jedoch einige Ausnahmen. Zum Beispiel ist Gl. führt keine implizite Typkonvertierung durch, wenn eine Ganzzahl mit einem Float verglichen wird.
Operator für die Fallgleichheit: ===
Viele der in Ruby integrierten Klassen, wie z. B. String, Range und Regexp, bieten ihre eigenen Implementierungen des Operators ===, auch bekannt als Groß- / Kleinschreibung, Dreifachgleichheit oder Dreifachgleichung. Da es in jeder Klasse unterschiedlich implementiert ist, verhält es sich je nach Objekttyp, für den es aufgerufen wurde, unterschiedlich. Im Allgemeinen wird true zurückgegeben, wenn das Objekt auf der rechten Seite zu dem Objekt auf der linken Seite gehört. Beispielsweise kann damit getestet werden, ob ein Objekt eine Instanz einer Klasse (oder einer ihrer Unterklassen) ist.
Das gleiche Ergebnis kann mit anderen Methoden erzielt werden, die wahrscheinlich am besten für den Job geeignet sind. Normalerweise ist es besser, Code zu schreiben, der leicht zu lesen ist, indem er so explizit wie möglich ist, ohne die Effizienz und Prägnanz zu beeinträchtigen.
Beachten Sie, dass das letzte Beispiel false zurückgegeben hat, da Ganzzahlen wie 2 Instanzen der Fixnum-Klasse sind, die eine Unterklasse der Integer-Klasse ist. Das ===, is_a? und instance_of? Methoden geben true zurück, wenn das Objekt eine Instanz der angegebenen Klasse oder einer Unterklasse ist. Die Methode instance_of ist strenger und gibt nur dann true zurück, wenn das Objekt eine Instanz dieser exakten Klasse und keine Unterklasse ist.
Das is_a? und kind_of? Methoden werden im Kernel-Modul implementiert, das von der Object-Klasse gemischt wird. Beide sind Aliase nach derselben Methode. Lassen Sie uns überprüfen:
Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Ausgabe: => true
Bereichsimplementierung von ===
Wenn der Operator === für ein Bereichsobjekt aufgerufen wird, gibt er true zurück, wenn der Wert rechts in den Bereich links fällt.
Denken Sie daran, dass der Operator === die Methode === des linken Objekts aufruft. Also (1..4) === 3 ist äquivalent zu (1..4). === 3. Mit anderen Worten, die Klasse des linken Operanden definiert, welche Implementierung der === Methode sein wird aufgerufen, daher sind die Operandenpositionen nicht austauschbar.
Regexp Implementierung von ===
Gibt true zurück, wenn die Zeichenfolge rechts mit dem regulären Ausdruck links übereinstimmt. / zen / === "Zazen heute üben" # Ausgabe: => true # ist dasselbe wie "Zazen heute üben" = ~ / zen /
Implizite Verwendung des Operators === für case / when-Anweisungen
Dieser Operator wird auch unter der Haube für case / when-Anweisungen verwendet. Das ist die häufigste Verwendung.
Wenn Ruby im obigen Beispiel implizit den doppelten Gleichheitsoperator (==) verwendet hätte, würde der Bereich 10..20 nicht als gleich einer Ganzzahl wie 15 angesehen. Sie stimmen überein, weil der dreifach gleiche Operator (===) ist implizit in allen case / when-Anweisungen verwendet. Der Code im obigen Beispiel entspricht:
Mustervergleichsoperatoren: = ~ und! ~
Die Operatoren = ~ (Equal-Tilde) und! ~ (Bang-Tilde) werden verwendet, um Zeichenfolgen und Symbole mit Regex-Mustern abzugleichen.
Die Implementierung der Methode = ~ in den Klassen String und Symbol erwartet einen regulären Ausdruck (eine Instanz der Regexp-Klasse) als Argument.
Die Implementierung in der Regexp-Klasse erwartet eine Zeichenfolge oder ein Symbol als Argument.
Wenn in allen Implementierungen die Zeichenfolge oder das Symbol mit dem Regexp-Muster übereinstimmt, wird eine Ganzzahl zurückgegeben, die die Position (den Index) der Übereinstimmung darstellt. Wenn keine Übereinstimmung vorliegt, wird null zurückgegeben. Denken Sie daran, dass in Ruby jeder ganzzahlige Wert "wahr" und null "falsch" ist, sodass der Operator = ~ in if-Anweisungen und ternären Operatoren verwendet werden kann.
Mustervergleichsoperatoren sind auch nützlich, um kürzere if-Anweisungen zu schreiben. Beispiel:
Der Operator! ~ Ist das Gegenteil von = ~. Er gibt true zurück, wenn keine Übereinstimmung vorliegt, und false, wenn eine Übereinstimmung vorliegt.
Weitere Informationen finden Sie in diesem Blogbeitrag .
quelle
:zen === "zen"
gibt false zurückRuby stellt verschiedene Methoden für den Umgang mit Gleichheit vor:
Lesen Sie weiter, indem Sie auf den unten stehenden Link klicken. Dadurch erhielt ich ein klares, zusammengefasstes Verständnis.
Hoffe es hilft anderen.
quelle
=== # --- Fallgleichheit
== # --- generische Gleichheit
beide funktionieren ähnlich, aber "===" macht sogar case-Anweisungen
hier der Unterschied
quelle
a==b
danna===b
. Ista===b
aber viel mächtiger.===
ist nicht symmetrisch unda===b
bedeutet etwas ganz anderes alsb===a
, geschweige denna==b
.Ich möchte den
===
Operator erweitern.===
ist kein Gleichheitsoperator!Nicht.
Lassen Sie uns diesen Punkt wirklich vermitteln.
Sie kennen sich vielleicht
===
als Gleichheitsoperator in Javascript und PHP aus, aber dies ist einfach kein Gleichheitsoperator in Ruby und hat eine grundlegend andere Semantik.Was macht
===
also?===
ist der Pattern Matching Operator!===
stimmt mit regulären Ausdrücken überein===
Überprüft die Bereichsmitgliedschaft===
prüft, ob es sich um eine Instanz einer Klasse handelt===
ruft Lambda-Ausdrücke auf===
prüft manchmal die Gleichheit, meistens aber nichtWie macht dieser Wahnsinn Sinn?
Enumerable#grep
verwendet===
interncase when
Anweisungen werden===
intern verwendetrescue
nutzt===
internAus diesem Grund können Sie in einer
case when
Anweisung reguläre Ausdrücke, Klassen und Bereiche und sogar Lambda-Ausdrücke verwenden .Einige Beispiele
Alle diese Beispiele funktionieren sowohl mit
pattern === value
als auch mitgrep
Methoden.quelle
Ich habe einen einfachen Test für all das geschrieben.
quelle