2010-11-13 22 views
13

我想要一個繼承的ruby類,通過類方法'知道'它的類名。在Ruby中'知道'類名的類方法?

class Parent 
    def self.whoami 
    ?? 
    end 
end 

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

所以我應該能夠調用:這是最好的一個人爲的例子說明

Parent.whomai 

和期望的「父母」一回,我應該然後能夠調用:

Child.whoami 

並期待「孩子」的回報我有一種感覺,在傳統語言中這可能是不可能的。但Ruby的元編程模型讓我感到驚訝。有什麼想法嗎?提前致謝。

回答

20

類方法是一種方法,其中的類是接收器,於是找到時該方法被調用(你看起來是要試圖在這裏做)只是檢查的self值的對象。

class Parent 
    def self.whoami 
    self 
    end 
end 

class Child < Parent 
end 

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

這似乎太容易了。謝謝。 – 2010-11-13 06:32:02

+0

['Module#name']有什麼問題(http://Ruby-Doc.Org/ruby-1.9/classes/Module.html#M000913)以及double'puts'的原因? – 2010-11-13 09:57:27

+1

沒有理由有一個返回self的方法,直接使用該對象:'放置父'。 Puts在後臺調用Parent.to_s來獲取類的字符串名稱。 – 2012-01-31 12:00:30

2

難道那Parent.class會告訴你嗎?

class Parent 
    def self.whoami 
    self.to_s 
    end 
end 

class Child < Parent 
end 

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

如果一個類的方法,'self'將返回類 – 2010-11-13 06:26:28

+2

出了什麼問題['模塊#name'(http://Ruby-Doc.Org/ruby -1.9 /班/ Module.html#M000913)? – 2010-11-13 09:57:48

+0

@Jörg我假設他正在做一些比返回名稱的類方法更復雜的事情,但你說得對,'Module#name'是正確的方法。 – 2010-11-14 01:21:02

15

獲取類名稱(模塊,實際)的方法只是Module#name。有沒有必要寫你自己:

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

然而,在Ruby中,真的沒有這樣的事情作爲一個「類名」,因爲在一些其他語言。在Ruby中,一個類只是一個像其他對象一樣的對象,像其他變量一樣被賦值給一個變量。

所有的Module#name方法都是循環遍歷系統中的所有常量,並檢查模塊是否已分配給它們中的任何一個,並返回該常量的名稱或nil(如果找不到)。

所以,就像其他任何對象一樣,一個類的「名稱」是真的是什麼都不是,只是用來引用它的任何變量。

實施例:

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

現在,類的 「name」 是foo。但是,Module#name返回nil,因爲foo不是一個常數。現在

bar = foo 
bar.name # => nil 

,在類的 「名」 是foobar,但Module#name顯然還是返回nil

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

現在,由於該類已被分配到一個常量,該常量的名稱將被視爲該類的名字......

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

&hellip;即使在常量被分配到不同的東西之後,

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

&hellip;即使在班級被分配到不同的常數之後。

Module#to_s使用Module#name如果不是nil,所以,打印類的名字,你根本就

puts Parent 

有真的完全沒有必要在其他的答案中所有複雜的絨毛。

1

假設你等級:

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