2010-10-11 9 views
96

¿Cuál es la diferencia entreclase Rubí tipos de casos y declaraciones

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, la primera de estas obras a veces y el segundo no lo hace, y otras veces , el segundo funciona y el primero no. ¿Por qué? ¿Cuál es la forma "correcta" de hacerlo?

+1

String es una clase. La clase de una clase es Clase. – Volte

Respuesta

167

debe utilizar:

case item 
    when MyClass 

que tenían el mismo problema: How to catch Errno::ECONNRESET class in "case when"?

+1

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

+2

Una advertencia que no se ha mencionado si se usa ActiveRecord. El método ActiveRecord === en las comparaciones de clases usa .is_a ?, lo que significa que las subclases de una clase se evaluarán como verdaderas en la sentencia case. https://github.com/rails/rails/blob/04cda1848cb847c2bdad0bfc12160dc8d5547775/activerecord/lib/active_record/core.rb#L135 –

1

Depende de la naturaleza de su variable item. Si es una instancia de un objeto, p.

t = 5 

entonces

t.class == Fixnum 

pero si se trata de una clase en sí por ejemplo

t = Array 

entonces será un objeto Class, por lo

t.class == Class 

EDITAR: consulte How to catch Errno::ECONNRESET class in "case when"? según lo indicado por Nakilon ya que mi respuesta podría ser incorrecta.

+2

'case' uses' === ' – Nakilon

+0

En Ruby, todo es" una instancia de un objeto ". –

4

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

obj.class es un objeto de tipo Class que describe la clase de obj. Si obj.class es MyClass, entonces obj se creó usando MyClass.new (aproximadamente). MyClass es un objeto del tipo Class que describe cualquier objeto creado usando MyClass.new.

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

45

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

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

es realmente

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

Entender que el caso está llamando a un método threequal (MyClass.===(item) por ejemplo), y que el método puede ser definido a hacer lo que quiera, y entonces usted puede utilizar el sentencia case con precisionw

+0

Si tengo 'arr = []', entonces noté que 'if Array === arr' evaluar a true, pero 'if arr === Array' se evaluará como falso. ¿Alguien puede ayudar a explicar? – Daniel

+4

=== es solo un método que se puede definir para hacer lo que el diseñador de una clase quiere que haga. Recuerde, también, que a === b realmente significa a. === b, de modo que si cambia una y a la vez, 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

Cuestiones relacionadas