2012-04-03 19 views
5

¿Cómo puedo obtener el nombre de clase de una instancia de BasicObject en Ruby? Por ejemplo, supongo que tengo esto:Obtener el nombre de la clase Ruby sin el método de clase

class MyObjectSystem < BasicObject 
end 
puts MyObjectSystem.new.class 

¿Cómo puedo hacer que este código tenga éxito?

EDIT: he encontrado que el método de instancia class del objeto se define como return rb_class_real(CLASS_OF(obj));. ¿Alguna forma de usar esto de Ruby?

+1

¿Puede dar una un ejemplo un poco más concreto de lo que estás tratando de hacer? ¿Estás preguntando "Si tengo una clase Foo que hereda de BasicObject, ¿hay alguna manera de identificar que una instancia de esa clase es 'Foo' en comparación con BasicObject"? no estoy seguro de lo que estas preguntando. –

+0

¡En realidad, sí exactamente! Cambiando la publicación para aclarar – Jwosty

+0

'MyObjectSystem.class.name'? –

Respuesta

8

pasé algún tiempo jugando con el IRB y se le ocurrió esto:

class BasicObject 
    def class 
    klass = class << self; self; end # get the object's singleton class 
    klass.superclass # the superclass of an object's singleton class is that object's class 
    end 
end 

que dará a cualquier objeto que hereda de BasicObject un método #class que se puede llamar.

Editar

una explicación más detallada a lo solicitado en los comentarios:

Digamos que tiene obj objeto que es una instancia de la clase Foo. obj obtiene sus métodos de instancia de aquellos que están definidos dentro de la clase Foo, además de los métodos definidos en la clase padre de Foo y así sucesivamente en la cadena de herencia. Rubí le permite definir métodos directamente en un objeto que sólo se puede acceder a ese objeto particular como éste

obj = Foo.new 
def obj.hello 
    puts "hello" 
end 

obj.hello #=> hello 

other_obj = Foo.new 
other_obj.hello #=> Method missing error 

La razón por la que puede hacer esto es debido a que cada objeto tiene algo que se llama una clase Singleton (o, a veces llamar a un eigenclass) que en realidad estás definiendo el método en. Esta clase singleton realmente existe en la cadena de herencia del objeto directamente debajo de la clase real del objeto. Eso hace que la clase real del objeto, Foo en este ejemplo, sea la superclase de la clase singleton del objeto.

La línea class << self que ve en la respuesta es una sintaxis especial para ingresar el alcance de la clase singleton de un objeto. Así, en el ejemplo anterior, también se puede definir un método en la clase singleton de un objeto como éste

class << obj 
    def goodbye 
    puts "goodbye" 
    end 
end 

obj.goodbye #=> goodbye 

así que la línea class << self; self; end está abriendo clase singleton del objeto (cualquier objeto que se encuentra actualmente self) y luego regresar self (self tiene ahora conviértase en la clase singleton), que luego puede asignarse a una variable para hacer lo que desee.

Recomendaría leer Metaprogramming Ruby si desea una mejor explicación de todo esto. Definitivamente te da una mejor comprensión del modelo de objetos Ruby en general.

+0

¡Ah, muchas gracias! Esto parece hacer el truco. – Jwosty

+3

¡Oh, eso es inteligente! –

+0

Eso es increíble. Me gustaría entender por qué y cómo funciona eso. ¿Podría darnos una explicación más detallada? –

1

Tengo que irme en unos minutos, así que no puedo probarlo yo mismo, pero parece que podría hacer un módulo separado que use ffi para llamar a rb_class_real desde libruby. Si tuviera más tiempo, lo probaría primero, pero nadie más ha respondido todavía y no quiero que te dejen totalmente en el frío.

+1

Muy bien, investigaré esto. ¡Gracias! ¿Pero sabes de una forma pura de Ruby? Eso sería realmente bueno. – Jwosty

0

Basado en la answer Jeff Smith, usted puede hacer esto sin modificar BasicObject:

class << object; self; end.superclass 

donde object es una instancia de un objeto cuya clase que desea, es decir,

irb(main):001:0> object = BasicObject.new 
(Object doesn't support #inspect) 
=> 
irb(main):002:0> class << object; self; end.superclass 
=> BasicObject 
Cuestiones relacionadas