Types de classe Ruby et instructions de cas


135

Quelle est la différence entre

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

et

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

Pour une raison quelconque, le premier de ces travaux fonctionne parfois et le second ne fonctionne pas, et d'autres fois, le second fonctionne et le premier ne fonctionne pas. Pourquoi? Quelle est la «bonne» façon de le faire?


1
String est une classe. La classe d'une classe est Classe.
Volte

Notez qu'il MyClass === objutilise la méthode Module # === pour vérifier s'il objs'agit d'une instance de MyClass.
sergio

Réponses:


234

Tu dois utiliser:

case item
when MyClass
...

J'ai eu le même problème: Comment attraper la classe Errno :: ECONNRESET dans "cas quand"?


1
Merci! Désolé de duper (ou une sorte de dupe), mais plusieurs recherches n'ont pas révélé la question précédente. Il semble que l'utilisation de === par l'instruction case soit un problème assez courant, maintenant que je vois que c'est le problème. Cela devrait probablement être souligné plus souvent dans les tutoriels et autres (mais je parie que de nombreux rédacteurs de tutoriels ne le savent pas non plus).
Daisy Sophia Hollman

4
Une mise en garde qui n'a pas été mentionnée si vous utilisez ActiveRecord. La méthode ActiveRecord === sur les comparaisons de classes utilise .is_a ?, ce qui signifie que les sous-classes d'une classe seront évaluées à true dans l'instruction case. github.com/rails/rails/blob/…
Jeremy Baker

61

Ouais, Nakilon a raison, vous devez savoir comment l'opérateur threequal === fonctionne sur l'objet donné dans la whenclause. En rubis

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

est vraiment

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

Comprenez que case appelle une méthode threequal ( MyClass.===(item)par exemple), et que cette méthode peut être définie pour faire ce que vous voulez, puis vous pouvez utiliser l'instruction case avec precisionw


Si je l'ai fait, arr = []j'ai remarqué que if Array === arrcela évaluera à vrai mais if arr === Arrayévaluera à faux. Quelqu'un peut-il s'il vous plaît aider à expliquer?
Daniel

4
=== est juste une méthode qui peut être définie pour faire tout ce que le concepteur d'une classe veut qu'il fasse. Souvenez-vous également que a === b signifie vraiment a. === b, donc si vous changez de a et de b, vous pouvez obtenir un comportement différent. Il n'y a aucune garantie que === soit commutatif. En fait, Array === Array est faux, mais Object === Object est vrai, donc Array redéfinit la sémantique de ===.
Fred


5

Dans Ruby, un nom de classe est une constante qui fait référence à un objet de type Classqui décrit une classe particulière. Cela signifie que dire MyClassen Ruby équivaut à dire MyClass.classen Java.

obj.classest un objet de type Classdécrivant la classe de obj. Si obj.classest MyClass, alors a objété créé en utilisant MyClass.new(grosso modo). MyClassest un objet de type Classqui décrit tout objet créé à l'aide de MyClass.new.

MyClass.classest la classe de l' MyClassobjet (c'est la classe de l'objet de type Classqui décrit tout objet créé à l'aide de MyClass.new). En d' autres termes, MyClass.class == Class.


1

Cela dépend de la nature de votre itemvariable. S'il s'agit d'une instance d'un objet, par exemple

t = 5

puis

t.class == Fixnum

mais si c'est une classe en soi par exemple

t = Array

alors ce sera un Classobjet, donc

t.class == Class

EDIT : veuillez vous référer à Comment attraper la classe Errno :: ECONNRESET dans "cas quand"? comme indiqué par Nakilon puisque ma réponse pourrait être fausse.


Dans Ruby, tout est "une instance d'un objet".
Eric Duminil
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.