2010-10-11 6 views
96

Was ist der Unterschied zwischenRuby-Klasse-Typen und case-Anweisungen

case item.class 
when MyClass 
    # do something here 
when Array 
    # do something different here 
when String 
    # do a third thing 
end 

und

case item.class 
when MyClass.class 
    # do something here 
when Array.class 
    # do something different here 
when String.class 
    # do a third thing 
end 

Aus irgendeinem Grund die erste dieser Werke manchmal und die zweite nicht, und zu anderen Zeiten , der zweite funktioniert und der erste nicht. Warum? Welcher ist der "richtige" Weg, es zu tun?

+1

String ist eine Klasse. Die Klasse einer Klasse ist Klasse. – Volte

Antwort

167

Sie verwenden müssen:

case item 
    when MyClass 

Ich hatte das gleiche Problem: How to catch Errno::ECONNRESET class in "case when"?

+1

Danke! Entschuldigen Sie, dass Sie getäuscht haben (oder Art von Betrogenen), aber mehrere Suchen haben diese vorherige Frage nicht angezeigt. Es scheint, dass die Verwendung von == durch die Case-Anweisung ein ziemlich häufiges Problem ist, jetzt, da ich sehe, dass dies das Problem ist. Dies sollte wahrscheinlich öfter in Tutorials und Ähnlichem erwähnt werden (aber ich wette, dass viele Tutorialautoren das auch nicht wissen). –

+2

Ein Vorbehalt, der bei Verwendung von ActiveRecord nicht erwähnt wurde. Die Methode ActiveRecord === für Klassenvergleiche verwendet .is_a ?, was bedeutet, dass Unterklassen einer Klasse in der case-Anweisung als true ausgewertet werden. https://github.com/rails/rails/blob/04cda1848cb847c2bdad0bfc12160dc8d5547775/activerecord/lib/active_record/core.rb#L135 –

1

Es hängt von der Natur Ihrer item Variable ab. Wenn es sich um eine Instanz eines Objekts handelt, z.

t = 5 

dann

t.class == Fixnum 

aber wenn es eine Klasse für sich ist beispiels

t = Array 

dann wird es ein Class Objekt sein, so

t.class == Class 

EDIT: Bitte beziehen Sie sich auf How to catch Errno::ECONNRESET class in "case when"? wie von Nakilon angegeben, da meine Antwort falsch sein könnte.

+2

'case' verwendet' === ' – Nakilon

+0

In Ruby ist alles" eine Instanz eines Objekts ". –

4

In Ruby, ein Klassenname ist eine Konstante, die Class auf ein Objekt vom Typ bezeichnet, die eine bestimmte Klasse beschreibt. Das bedeutet, dass MyClass in Ruby zu sagen, MyClass.class in Java entspricht.

obj.class ist ein Objekt vom Typ Class, das die Klasse obj beschreibt. Wenn obj.classMyClass ist, dann wurde obj mit MyClass.new erstellt (grob gesagt). MyClass ist ein Objekt vom Typ Class, das jedes Objekt beschreibt, das mit MyClass.new erstellt wurde.

MyClass.class die Klasse des Objekts MyClass ist (es ist die Klasse des Objekts des Typs Class die jedes Objekt beschreibt MyClass.new erstellt). Mit anderen Worten, MyClass.class == Class.

45

Ja, Nakilon ist richtig, Sie müssen wissen, wie der dreibinige Operator === auf dem Objekt funktioniert, das in der when Klausel angegeben ist.In Ruby

case item 
when MyClass 
... 
when Array 
... 
when String 
... 

ist wirklich

if MyClass === item 
... 
elsif Array === item 
... 
elsif String === item 
... 

dass Fall Verstehen Sie eine threequal Methode ruft (MyClass.===(item) zum Beispiel), und das Verfahren kann definiert werden, um zu tun, was Sie wollen, und dann können Sie mit dem Case-Anweisung mit precisionw

+0

Wenn ich 'arr = []' habe, dann habe ich festgestellt, dass 'wenn Array === arr' wird evaluate to true aber 'if arr === Array' wird zu false ausgewertet. Kann mir bitte jemand helfen erklären? – Daniel

+4

=== ist nur eine Methode, die definiert werden kann, um zu tun, was auch immer der Designer einer Klasse tun möchte. Denken Sie auch daran, dass a === b wirklich a. === b bedeutet. Wenn Sie also a und b umschalten, können Sie ein unterschiedliches Verhalten erhalten. Es gibt keine Garantie, dass === kommutativ ist. In der Tat, Array === Array ist falsch, aber Object === Objekt ist wahr, daher definiert Array die Semantik von === neu. – Fred

Verwandte Themen