Determinar el tipo de un objeto en ruby

365

Usaré python como ejemplo de lo que estoy buscando (puedes pensar en él como un pseudocódigo si no conoces Python):

>>> a = 1
>>> type(a)
<type 'int'>

Sé que en ruby ​​puedo hacer:

1.9.3p194 :002 > 1.class
 => Fixnum 

¿Pero es esta la forma correcta de determinar el tipo de objeto?

Zippy Zeppoli
fuente
55
@ JörgWMittag Sin embargo, AFAICR es lo que hace `type` en Python, aunque mi memoria es borrosa. Necesitaría isinstance o verificaría si responde. Pero simplemente diciendo "NOES !!!" no es realmente útil, ahora, ¿verdad? En cambio, considere ser educativo.
Dave Newton
44
@ JörgWMittag Aunque simpatizo, OP proporcionó un código para imitar en Ruby. A menos que realmente eduque a la OP diciendo que los noes no son útiles, la OMI. E incluso si lo hiciera, probablemente sería solo informativo, ya que OP definió lo que quería a través del código.
Dave Newton
55
@ JörgWMittag: en Ruby todo es un Objeto, por lo que no hay tipos primitivos como los hay en Python (int, long, boolean, etc.) Como resultado dentro de Ruby, las clases son definiciones de tipo. Esto tampoco se limita a Ruby, la palabra clase y tipo son sinónimos en varios otros idiomas, y más ampliamente en la teoría OOP.
ocodo
66
Como realmente estamos hablando de Ruby aquí, Tipos y Clases son sinónimos, no hay debate sobre esto, todos los valores son Objetos. Entonces, para cualquiera que simplemente habla de Ruby, las clases son tipos. - ref: ruby-lang.org/en/about
ocodo
2
@ JörgWMittag Ese ensayo es bastante informativo hasta ahora, y leeré el resto cuando tenga la oportunidad. En particular, Cook parece articular bastante bien (y con mucho más conocimiento de fondo que yo) por qué es incorrecto afirmar (como lo hizo uno de mis profesores) que Python, Ruby y otros lenguajes de tipo dinámico "no son realmente objeto orientado "(lo que probablemente quiso decir, sin darse cuenta, era que no estaban orientados a ADT). Pero Ruby no está tipificado estáticamente, por lo que no tiene ADT en el sentido que Cook describe, por lo que sus objeciones sobre la base de esa distinción no son útiles.
Kyle Strand

Respuestas:

608

La forma correcta de determinar el "tipo" de un objeto, que es un término tambaleante en el mundo de Ruby, es llamar object.class.

Dado que las clases pueden heredar de otras clases, si desea determinar si un objeto es "de un tipo particular", puede llamar object.is_a?(ClassName)para ver si objectes de tipo ClassNameo derivado de él.

Normalmente, la verificación de tipo no se realiza en Ruby, sino que los objetos se evalúan en función de su capacidad de responder a métodos particulares, comúnmente llamados " mecanografía de pato ". En otras palabras, si responde a los métodos que desea, no hay razón para ser particular sobre el tipo.

Por ejemplo, object.is_a?(String)es demasiado rígido ya que otra clase podría implementar métodos que lo convierten en una cadena, o hacer que se comporte de manera idéntica a cómo se comporta la cadena. object.respond_to?(:to_s)sería una mejor manera de probar que el objeto en cuestión hace lo que quieres.

tadman
fuente
13
-1. #classno no devolver el tipo del objeto, devuelve su clase . El nombre debe ser un regalo muerto. Clase y tipo son dos conceptos completamente diferentes en OO.
Jörg W Mittag
78
@ Jörg W Mittag: No estoy de acuerdo. "Clase" y "velocidad del procesador" (para elegir un ejemplo) son dos conceptos completamente diferentes, pero "clase" y "tipo" son conceptos estrechamente relacionados. Por ejemplo, esto es lo que dice el artículo de Wikipedia sobre la clase : "En la programación orientada a objetos, una clase es una construcción que se utiliza para definir un tipo distinto". tadman estaba siendo útil para el interrogador.
Teemu Leisti
18
@ JörgWMittag En Ruby lo más parecido a typeofC, JavaScript y otros es class. No existe un sistema de protocolo formal en Ruby como en otros lenguajes, siendo Objective-C el pariente más pequeño de Smalltalk con eso. Si está definiendo "tipo" como "objeto que responde a un conjunto particular de métodos con resultados aceptables", entonces no hay forma de afirmarlo. Es demasiado flojo. La mayoría de las veces en Ruby cuando se refiere al tipo de un objeto, se entiende que estás hablando de la clase. Utilicé el término tipo entre comillas por esa misma razón.
tadman
14
@ Jörg W Mittag: Sigo afirmando que "clase" y "tipo" ciertamente no son conceptos completamente diferentes en OO, como lo demuestra la cita. (También: ¿cómo se declara una variable en Java Al dar? Ya sea el tipo o la clase de la variable, seguido de su nombre: " int i" o " Integer j".) Tadman respondió a la pregunta de una manera que parecía satisfacer tanto el interrogador y el público en general, mientras aclara la terminología que utiliza Ruby. No tengo ningún interés en entrar en una división académica sobre los puntos más finos de la terminología orientada a objetos, así que tenga la última palabra.
Teemu Leisti
11
@TeemuLeisti La mayor parte del problema aquí proviene del hecho de que todo en Ruby es un objeto, y también lo tiene una clase, mientras que en prácticamente todos los demás idiomas hay tipos primitivos que no son objetos y no tienen clase, en contraste con los objetos que sí lo hacen. Cuando no existe un tipo puro, y no hay forma de definirlo formalmente, el significado se vuelve especialmente confuso en el mundo de Ruby. Matz no se está adhiriendo estrictamente a ninguna escuela particular de pensamiento aquí que no sea la suya.
tadman
81

También puedes probar: instance_of?

p 1.instance_of? Fixnum    #=> True
p "1".instance_of? String  #=> True
p [1,2].instance_of? Array #=> True
Arup Rakshit
fuente
44

A menudo en Ruby, en realidad no te importa cuál es la clase del objeto, per se, solo te importa que responda a un determinado método. Esto se conoce como Duck Typing y lo verá en todo tipo de bases de código Ruby.

Entonces, en muchos (si no la mayoría) de los casos, es mejor usar Duck Typing usando #respond_to?(method):

object.respond_to?(:to_i)
Stuart M
fuente
1
punto valido. no responde la pregunta pero responde al espíritu de la pregunta.
user566245
@ user566245 bueno, responde_to? (: the_question), pero, como dijiste, no responde la pregunta, solo proporciona información relacionada. Las respuestas bastante seguras necesitan responder la pregunta.
R. Rincón
17

Yo diría que sí". Como "Matz" había dicho algo como esto en una de sus charlas, "los objetos de Ruby no tienen tipos". No todo, sino la parte que está tratando de transmitirnos. ¿Por qué alguien habría dicho "Todo es un objeto" entonces? Para agregar, dijo: "Los datos tienen tipos, no objetos".

Entonces podríamos disfrutar esto.

https://www.youtube.com/watch?v=1l3U1X3z0CE

Pero a Ruby no le importa mucho el tipo de objeto, solo la clase. Usamos clases, no tipos. Todos los datos tienen una clase.

12345.class

'my string'.class

También pueden tener antepasados

Object.ancestors

También tienen metaclases, pero te guardaré los detalles al respecto.

Una vez que conozca la clase, podrá buscar qué métodos puede usar para ella. Ahí es donde se necesita el "tipo de datos". Si realmente quieres entrar en detalles, mira hacia arriba ...

"El modelo de objetos de rubí"

Este es el término utilizado para la forma en que Ruby maneja los objetos. Todo es interno, por lo que realmente no se ve mucho de esto, pero es bueno saberlo. Pero ese es otro tema.

¡Si! La clase es el tipo de datos. Los objetos tienen clases y los datos tienen tipos. Entonces, si conoce las bases de datos, entonces sabe que solo hay un conjunto finito de tipos.

números de bloques de texto

Douglas G. Allen
fuente
Por ejemplo,Object.ancestors # => [Object, Kernel, BasicObject]
Dorian