2010-11-13 8 views
13

Quiero que una clase de ruby ​​heredada 'conozca' su nombre de clase a través de un método de clase. Esto se ilustra mejor con un ejemplo artificial:Método de clase para 'saber' el nombre de clase en Ruby?

class Parent 
    def self.whoami 
    ?? 
    end 
end 

class Child < Parent 
    #No code should be needed. 
end 

así que debería ser capaz de llamar:

Parent.whomai 

y esperar un retorno de "padre" debería entonces ser capaz de llamar:

Child.whoami 

y esperamos un retorno de "Niño" Tengo la sensación de que en los idiomas convencionales esto podría no ser posible. Pero el modelo de metaprogramación de Ruby me ha sorprendido antes. ¿Alguna idea? Gracias por adelantado.

Respuesta

20

un método de clase es un método en la clase es el receptor, por lo que encontrar el objeto sobre el que se invoca el método (lo que parece estar tratando de hacer aquí) simplemente inspeccionar el valor de self.

class Parent 
    def self.whoami 
    self 
    end 
end 

class Child < Parent 
end 

puts Parent.whoami #=> Parent 
puts Child.whoami #=> Child 
+0

Eso parecía demasiado fácil. Gracias. –

+0

¿Qué pasa con ['Module # name'] (http://Ruby-Doc.Org/ruby-1.9/classes/Module.html#M000913) y por qué el doble' puts'? –

+1

No hay razón para tener un método que devuelve self, use el objeto directamente: 'puts Parent'. Puts está llamando a Parent.to_s detrás de escena para obtener un nombre de cadena de la clase. –

2

¿No es eso lo que Parent.class le dirá?

class Parent 
    def self.whoami 
    self.to_s 
    end 
end 

class Child < Parent 
end 

> Parent.whoami 
=> "Parent" 
> Child.whoami 
=> "Child" 
+0

Si es un método de clase, 'self' volverá a la clase –

+2

¿Qué hay de malo en [' Módulo # name'] (http://Ruby-Doc.Org/ruby -1.9/classes/Module.html # M000913)? –

+0

@ Jörg Suponía que estaba haciendo algo un poco más complicado que un método de clase que le devolvió un nombre, pero tiene razón en que 'Nombre del módulo #' es la forma correcta de hacerlo. –

15

El método para obtener el nombre de una clase (módulo, en realidad) es sólo Module#name. No hay necesidad de escribir su propia:

Parent.name # => 'Parent' 
Child.name # => 'Child' 

Sin embargo, en Ruby, en realidad no hay tal cosa como un "nombre de la clase", ya que es en algunos otros idiomas. En Ruby, una clase es simplemente un objeto como cualquier otro objeto que se asigna a una variable como cualquier otra variable.

Todo el método Module#name hace un ciclo a través de todas las constantes en el sistema y verifica si el módulo ha sido asignado a cualquiera de ellas, y devuelve el nombre de esa constante nil si no puede encontrar ninguna.

Por lo tanto, al igual que cualquier otro objeto, el "nombre" de una clase es realmente nada más que cualquier variable que utilice para referirse a ella.

Ejemplo:

foo = Class.new 
foo.name # => nil 

Ahora, el "nombre" de la clase es foo. Sin embargo, Module#name devuelve nil, porque foo no es una constante.

bar = foo 
bar.name # => nil 

Ahora, el "nombre" de la clase es tantofoo y bar, pero, evidentemente, todavía Module#name devuelve nil.

BAZ = foo 
foo.name # => 'BAZ' 

Ahora, ya que la clase ha sido asignado a una constante, el nombre de esa constante se considerará nombre y hellip de esa clase;

BAZ = nil 
foo.name # => 'BAZ' 

& hellip; incluso después de que la constante haya sido asignada a algo diferente y & hellip;

QUX = foo 
QUX.name # => 'BAZ' 

& hellip; incluso después de que la clase ha sido asignada a una constante diferente.

Module#to_s utiliza Module#name si no es nil, por lo que, para imprimir el nombre de una clase, sólo tiene que hacer

puts Parent 

Realmente no hay absolutamente ninguna necesidad de que todo el complejo de la pelusa en las otras respuestas.

1

Supongamos que la clase:

class ABC 
def self.some_method 
    self.name #it will return 'ABC' 
    self.name.constantize #it will return ABC 
end 
end 
Cuestiones relacionadas