Tipi di classe Ruby e dichiarazioni di casi


135

Qual è la differenza tra

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

e

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

Per qualche motivo, il primo di questi funziona a volte e il secondo no, e altre volte, il secondo funziona e il primo no. Perché? Qual è il modo "corretto" per farlo?


1
String è una classe. La classe di una classe è Class.
Volte,

Si noti che MyClass === objutilizza il metodo Module # === per verificare se objè un'istanza di MyClass.
sergio

Risposte:


234

Devi usare:

case item
when MyClass
...

Ho avuto lo stesso problema: Come catturare la classe Errno :: ECONNRESET nel "caso in cui"?


1
Grazie! Mi dispiace ingannare (o una specie di ingannare), ma diverse ricerche non hanno sollevato la domanda precedente. Sembra che l'uso di === dall'istruzione case sia un problema abbastanza comune, ora che vedo che questo è il problema. Questo dovrebbe probabilmente essere sottolineato più spesso nei tutorial e simili (ma scommetto che molti scrittori di tutorial non ne sono nemmeno a conoscenza).
Daisy Sophia Hollman,

4
Un avvertimento che non è stato menzionato se si utilizza ActiveRecord. Il metodo ActiveRecord === nei confronti di classi utilizza .is_a ?, il che significa che le sottoclassi di una classe verranno valutate come vere nell'istruzione case. github.com/rails/rails/blob/…
Jeremy Baker

61

Sì, Nakilon ha ragione, devi sapere come funziona l'operatore threequal === sull'oggetto indicato nella whenclausola. In rubino

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

è davvero

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

Comprendi che case sta chiamando un metodo a tre ( MyClass.===(item)ad esempio) e che quel metodo può essere definito per fare quello che vuoi, e quindi puoi usare l'istruzione case con precisionw


In arr = []tal caso if Array === arr, ho notato che valuterà vero ma if arr === Arrayvaluterà falso. Qualcuno può aiutare a spiegare?
Daniel

4
=== è solo un metodo che può essere definito per fare qualunque cosa il progettista di una classe voglia che faccia. Ricorda, inoltre, che a === b significa davvero a. === b, quindi se cambi aeb, puoi ottenere un comportamento diverso. Non vi è alcuna garanzia che === sia commutativo. In effetti, Array === Array è falso, ma Object === Object è vero, quindi Array sta ridefinendo la semantica di ===.
Fred


5

In Ruby, il nome di una classe è una costante che si riferisce a un oggetto di tipo Classche descrive una particolare classe. Ciò significa che dire MyClassin Ruby equivale a dire MyClass.classin Java.

obj.classè un oggetto di tipo che Classdescrive la classe di obj. Se obj.classè MyClass, allora è objstato creato usando MyClass.new(approssimativamente parlando). MyClassè un oggetto di tipo Classche descrive qualsiasi oggetto creato usando MyClass.new.

MyClass.classè la classe MyClassdell'oggetto (è la classe dell'oggetto di tipo Classche descrive qualsiasi oggetto creato usando MyClass.new). In altre parole, MyClass.class == Class.


1

Dipende dalla natura della tua itemvariabile. Se è un'istanza di un oggetto, ad es

t = 5

poi

t.class == Fixnum

ma se è una classe in sé ad es

t = Array

allora sarà un Classoggetto, quindi

t.class == Class

EDIT : fare riferimento a Come catturare la classe Errno :: ECONNRESET nel "caso in cui"? come affermato da Nakilon poiché la mia risposta potrebbe essere sbagliata.


In Ruby, tutto è "un'istanza di un oggetto".
Eric Duminil,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.