Tipos de clase de Ruby y declaraciones de casos


135

Cuál es la diferencia entre

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

y

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

Por alguna razón, el primero de estos funciona a veces y el segundo no, y otras veces, el segundo funciona y el primero no. ¿Por qué? ¿Cuál es la forma "adecuada" de hacerlo?


1
La cadena es una clase. La clase de una clase es Clase.
Volte

Tenga en cuenta que MyClass === objutiliza el método Módulo # === para verificar si objes una instancia de MyClass.
sergio

Respuestas:


234

Debes usar:

case item
when MyClass
...

Tuve el mismo problema: ¿Cómo atrapar Errno :: clase ECONNRESET en "caso cuando"?


1
¡Gracias! Perdón por engañar (o una especie de engaño), pero varias búsquedas no arrojaron esa pregunta anterior. Parece que el uso de === por la declaración del caso es un problema bastante común, ahora que veo que este es el problema. Esto probablemente debería señalarse con más frecuencia en tutoriales y demás (pero apuesto a que muchos escritores de tutoriales tampoco lo saben).
Daisy Sophia Hollman

44
Una advertencia que no se ha mencionado si se usa ActiveRecord. El método ActiveRecord === en las comparaciones de clases utiliza .is_a ?, lo que significa que las subclases de una clase se evaluarán como verdaderas en la declaración del caso. github.com/rails/rails/blob/…
Jeremy Baker

61

Sí, Nakilon es correcto, debe saber cómo funciona el operador threequal === en el objeto dado en la whencláusula. En rubí

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

realmente es

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

Comprenda que case llama a un método threequal ( MyClass.===(item)por ejemplo), y ese método se puede definir para hacer lo que quiera, y luego puede usar la declaración de caso con precisiónw


Si lo he hecho arr = [], noté que if Array === arrse evaluará como verdadero pero if arr === Arrayse evaluará como falso. ¿Alguien puede ayudarme a explicar?
Daniel

44
=== es solo un método que se puede definir para hacer lo que el diseñador de una clase quiera que haga. Recuerde, también, que a === b realmente significa a. === b, por lo que si cambia a y b, puede obtener un comportamiento diferente. No hay garantía de que === sea conmutativo. De hecho, Array === Array es falso, pero Object === Object es verdadero, por lo que Array está redefiniendo la semántica de ===.
Fred


5

En Ruby, un nombre de clase es una constante que se refiere a un objeto de tipo Classque describe una clase en particular. Eso significa que decir MyClassen Ruby es equivalente a decir MyClass.classen Java.

obj.classes un objeto de tipo que Classdescribe la clase de obj. Si obj.classes así MyClass, objse creó usando MyClass.new(aproximadamente). MyClasses un objeto de tipo Classque describe cualquier objeto creado usando MyClass.new.

MyClass.classes la clase del MyClassobjeto (es la clase del objeto de tipo Classque describe cualquier objeto creado usando MyClass.new). En otras palabras, MyClass.class == Class.


1

Depende de la naturaleza de su itemvariable. Si es una instancia de un objeto, p. Ej.

t = 5

luego

t.class == Fixnum

pero si es una clase en sí misma, por ejemplo

t = Array

entonces será un Classobjeto, entonces

t.class == Class

EDITAR : consulte Cómo capturar la clase Errno :: ECONNRESET en "caso cuando"? como dijo Nakilon ya que mi respuesta podría estar equivocada.


En Ruby, todo es "una instancia de un objeto".
Eric Duminil
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.