2010-11-13 26 views
13

Chcę, aby dziedziczona klasa ruby ​​"znała" jej nazwę klasy za pomocą metody klasy. Najlepiej to ilustruje contrived przykład:Metoda klasy "Znać" nazwę klasy w Ruby?

class Parent 
    def self.whoami 
    ?? 
    end 
end 

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

Więc powinienem móc zadzwonić:

Parent.whomai 

i oczekiwać zwrotu "dominująca" powinien być w stanie zadzwonić:

Child.whoami 

i oczekuj zwrotu "Dziecko" Mam wrażenie, że w językach konwencjonalnych może to nie być możliwe. Ale model metaprogramowania Ruby zadziwił mnie wcześniej. jakieś pomysły? Z góry dziękuję.

Odpowiedz

20

Class Method to metoda, gdzie klasa jest odbiornik, tak aby znaleźć obiekt, na którym metoda jest wywoływana (co wydaje się być stara się zrobić tutaj) po prostu sprawdzić wartość self.

class Parent 
    def self.whoami 
    self 
    end 
end 

class Child < Parent 
end 

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

To wydawało się zbyt łatwe. Dzięki. –

+0

Co jest nie tak z ['Module # name'] (http://Ruby-Doc.Org/ruby-1.9/classes/Module.html#M000913) i dlaczego podwójne' puts'? –

+1

Nie ma powodu, aby mieć metodę, która zwraca self, używaj bezpośrednio obiektu: 'puts Parent'. Puts dzwoni do Parent.to_s za kulisami, aby uzyskać nazwę napisu klasy. –

2

Czy to nie jest to, co Parent.class powie?

class Parent 
    def self.whoami 
    self.to_s 
    end 
end 

class Child < Parent 
end 

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

jeśli jego metody klasy, 'self' powróci klasę –

+2

Co jest złego w [' Module # name'] (http://Ruby-Doc.Org/ruby -1,9/classes/Module.html # M000913)? –

+0

@ Jörg Przyjąłem, że robi coś trochę bardziej skomplikowanego niż metoda klasowa, która zwróciła nazwę, ale masz rację, że "Nazwa modułu" jest właściwym sposobem na zrobienie tego. –

15

Sposób, aby uzyskać nazwę klasy (moduł, faktycznie) jest po prostu Module#name. Nie ma potrzeby, aby napisać swój własny:

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

Jednak w Ruby, naprawdę nie ma czegoś takiego jak „nazwa klasy”, jak jest w innych językach. W Ruby klasa jest po prostu obiektem, jak każdy inny obiekt, który zostanie przypisany do zmiennej jak każda inna zmienna.

Metoda ta polega na przeplataniu wszystkich stałych w systemie i sprawdzeniu, czy moduł został przypisany do którejkolwiek z nich i zwrocie tej stałej nazwy lub nil, jeśli nie może znaleźć żadnych.

Tak, jak każdy inny obiekt, "nazwa" klasy to naprawdę nic, bez względu na zmienną, której używasz do odniesienia.

Przykład:

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

Teraz "nazwa" klasy jest foo. Jednak Module#name zwraca nil, ponieważ foo nie jest stałą.

bar = foo 
bar.name # => nil 

Teraz "nazwa" klasy jest zarównofoo i bar, ale Module#name oczywiście nadal zwraca nil.

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

Teraz, ponieważ klasa została przypisana do stałej, nazwa tej stałej będzie uważana za nazwę klasy & hellip;

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

& hellip; nawet po tym, jak stała została przypisana do czegoś innego i & hellip;

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

& hellip; nawet po przypisaniu klasy do innej stałej.

Module#to_s wykorzystuje Module#name jeśli nie jest nil, tak, aby wydrukować nazwę klasy, po prostu zrobić

puts Parent 

Jest naprawdę absolutnie nie potrzeba całego kompleksu puchu w innych odpowiedzi.

1

Załóżmy klasę:

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