2010-08-06 7 views
53

In Ruby, was ist der Unterschied zwischen == und ===? Die RDoc sagt=== vs. == in Ruby

Fallgleichheit-For-Klasse Objekt, effektiv die gleichen wie # == Aufruf, aber in der Regel durch Abkömmlinge überschrieben sinnvollen Semantik bei Aussagen zu liefern.

Ist #== das gleiche wie ==? Und könnten Sie ein Beispiel dafür geben, wann/wie dies in Fallanweisungen verwendet wird?

+0

Ich denke, die beste Antwort hier http://StackOverflow.com/a/4467823/5048945 –

Antwort

107

Die beiden wirklich nichts miteinander zu tun haben. Insbesondere #== ist der Gleichheitsoperator und #=== hat absolut nichts mit Gleichheit. Ich persönlich finde es ziemlich schade, dass #===-#== so ähnlich aussieht, verwendet das Gleichheitszeichen und oft genannt wird die Fall Gleichheitsoperator, triple equals Operator oder threequals Operator, wenn es wirklich nichts mit Gleichheit zu tun hat.

Ich rufe #=== die Fall Subsumption Operator (es ist das beste, was ich könnte kommen, ich bin offen für Vorschläge, vor allem von englischen Muttersprachlern).

Die beste Art zu beschreiben a === b ist "Wenn ich eine Schublade mit der Bezeichnung a habe, macht es Sinn, b drin zu setzen?"

So zum Beispiel, Module#=== testet ob b.is_a?(a). Wenn Sie Integer === 2 haben, macht es Sinn, 2 in einem Feld mit der Bezeichnung Integer zu setzen? Ja tut es. Was ist mit Integer === 'hello'? Offensichtlich nicht.

Ein anderes Beispiel ist Regexp#===. Es testet auf eine Übereinstimmung. Ist es sinnvoll, 'hello' in eine Box mit der Bezeichnung /el+/ einzutragen? Ja tut es.

Für Sammlungen wie Bereiche ist Range#=== als Mitgliedschaftstest definiert: Es macht Sinn, ein Element in ein Feld mit einer Sammlung zu setzen, wenn dieses Element in der Sammlung ist.

Also, das ist, was #=== tut: es testet, ob das Argument unter dem Empfänger subsumiert werden kann.

Was muss das mit case Ausdrücke? Ganz einfach: in rescue

case foo 
when bar 
    baz 
end 

ist die gleiche wie

if bar === foo 
    baz 
end 
+4

'Array # ===' ist nicht als Mitgliedschaft in Ruby 1.8 oder 1.9.1 definiert. 'Bereich # ===' ist jedoch. – sepp2k

+1

@ Sepp2k: Du hast Recht. Das ist es, was ich für eine vernünftige Semantik empfinde, ohne zuerst die Dokumentation zu überprüfen. –

+0

Das ist neu für mich. Gut zu wissen! – Karl

10

Ja, durch #== bedeutet das Dokument "die Instanzmethode == des aktuellen Objekts".

=== ist bei Aussagen als solche verwendet:

case obj 
when x 
    foo 
when y 
    bar 
end 

die gleiche wie

if x === obj 
    foo 
elsif y === obj 
    bar 
end 

Einige Klassen, die ihre eigenen definieren Ist === sind Range (zu handeln, wie include?), Klasse (bis handle wie obj.is_a?(klass)) und Regexp (um wie =~ zu handeln, außer dass ein boolescher Wert zurückgegeben wird). Einige Klassen, die nicht ihre eigenen === definieren, sind die numerischen Klassen und String.

So

case x 
when 0 
    puts "Lots" 
when Numeric 
    puts(100.0/x) 
when /^\d+$/ 
    puts(100.0/x.to_f) 
default 
    raise ArgumentError, "x is not a number or numeric string" 
end 

ist die gleiche wie

if 0 == x 
    puts "Lots" 
elsif x.is_a? Numeric 
    puts(100.0/x) 
elsif x =~ /^\d+$/ 
    puts(100.0/x.to_f) 
else 
    raise ArgumentError, "x is not a number or numeric string" 
end 
+0

Neugierig, wenn Sie eine Zeichenfolge in der When-Anweisung setzen würde, wäre es ähnlich zu sagen 'case x; wenn string -> if "string" == x'? – the12

+1

@ the12 Fragen Sie, ob Ruby automatisch Anführungszeichen um einen Bezeichner hinzufügt, oder war das ein Tippfehler? Wie auch immer 'Fall x; wenn string 'äquivalent zu 'if string === x' ist, was, wenn 'string' eine Zeichenkette enthält, äquivalent zu 'if string == x' ist. Ebenso "Fall x; wenn "string" 'äquivalent ist zu" if "string" === x' und 'if" string "== x'. – sepp2k

3

Fun Tatsache ist === auch Ausnahmen verwendet übereinstimmen Hier ist ein Beispiel

class Example 
    def self.===(exception) 
    puts "Triple equals has been called." 
    true 
    end 
end 

raise rescue Example 
# => prints "Triple equals has been called." 
# => no exception raised 

Dieser verwendet wird um Systemfehler zu vergleichen.

SystemCallError.=== wurde definiert, um wahr zurückzugeben, wenn beide dasselbe errno haben. Bei diesem System können beide Fehler mit der gleichen Fehlernummer wie Errno::EAGAIN und Errno::EWOULDBLOCK gerettet werden, indem nur einer von ihnen aufgelistet wird.