2010-11-13 15 views
13

Voglio una classe ruby ​​ereditata per "conoscere" il suo nome di classe tramite un metodo di classe. Questo è meglio illustrato da un esempio inventato:Metodo di classe per "conoscere" il nome della classe in Ruby?

class Parent 
    def self.whoami 
    ?? 
    end 
end 

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

quindi dovrei essere in grado di chiamare:

Parent.whomai 

e si aspettano un ritorno di "Parent" Dovrei quindi essere in grado di chiamare:

Child.whoami 

e aspettarsi un ritorno di "Bambino" Ho la sensazione che nei linguaggi convenzionali questo potrebbe non essere possibile. Ma il modello di metaprogrammazione di Ruby mi ha stupito prima. qualche idea? Grazie in anticipo.

risposta

20

un metodo della classe è un metodo in cui la classe è il ricevitore, in modo da trovare l'oggetto su cui viene richiamato il metodo (quello in cui sembra essere cercando di fare qui) semplicemente controllare il valore di self.

class Parent 
    def self.whoami 
    self 
    end 
end 

class Child < Parent 
end 

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

Sembrava troppo semplice. Grazie. –

+0

Cosa c'è di sbagliato in ['Module # name'] (http://Ruby-Doc.Org/ruby-1.9/classes/Module.html#M000913) e perché il doppio' puts'? –

+1

Non c'è alcun motivo per avere un metodo che ritorni da sé, utilizzare direttamente l'oggetto: 'puts Parent'. Puts chiama Parent.to_s dietro le quinte per ottenere un nome di stringa della classe. –

2

Non è quello che lo dirà Parent.class?

class Parent 
    def self.whoami 
    self.to_s 
    end 
end 

class Child < Parent 
end 

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

Se la sua un metodo di classe, 'self' restituirà la classe –

+2

Cosa c'è di sbagliato con [' Modulo # name'] (http://Ruby-Doc.Org/ruby -1.9/classes/Module.html # M000913)? –

+0

@ Jörg Immagino che stia facendo qualcosa di un po 'più complicato di un metodo di classe che ha restituito un nome, ma hai ragione che "Nome modulo #" è il modo corretto per farlo. –

15

Il metodo per ottenere il nome di una classe (modulo, in realtà) è solo Module#name. Non c'è alcuna necessità di scrivere il proprio:

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

Tuttavia, in Ruby, non c'è davvero una cosa come un "nome di classe" in quanto v'è in alcune altre lingue. In Ruby, una classe è semplicemente un oggetto come qualsiasi altro oggetto che viene assegnato a una variabile come qualsiasi altra variabile.

Tutto il metodo Module#name esegue il ciclo di tutte le costanti nel sistema e controlla se il modulo è stato assegnato a uno di essi e restituisce il nome di tale costante o nil se non ne trova alcuno.

Quindi, proprio come qualsiasi altro oggetto, il "nome" di una classe è veramente, ma non importa quale variabile si usa per riferirsi ad esso.

Esempio:

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

Ora, il "nome" della classe è foo. Tuttavia, Module#name restituisce nil, perché foo non è una costante.

bar = foo 
bar.name # => nil 

Ora, il "nome" della classe è siafoo e bar, ma Module#name ovviamente restituisce comunque nil.

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

Ora, dal momento che la classe è stato assegnato a una costante, il nome di quel costante sarà considerato nome & hellip di quella classe;

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

& hellip; anche dopo che la costante è stata assegnata a qualcosa di diverso e & hellip;

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

& hellip; anche dopo che la classe è stata assegnata a una costante diversa.

Module#to_s usa Module#name se non è nil, così, per stampare il nome di una classe, è sufficiente fare

puts Parent 

Non c'è davvero alcun bisogno di tutto il complesso fluff nelle altre risposte.

1

Supponiamo di classe:

class ABC 
def self.some_method 
    self.name #it will return 'ABC' 
    self.name.constantize #it will return ABC 
end 
end 
Problemi correlati