2011-11-26 70 views
3

我正在閱讀的紅寶書已經讓我困惑了一下。如果我執行以下操作,我完全理解代碼拋出錯誤的原因;ruby​​中的類方法語法

class Person 
    def show_name 
    puts @name 
    end 
end 

person = Person.new 
person.show_name 
Person.show_name #(note the capital P) this line falls over 

它拋出一個錯誤,指出Person類沒有一個叫SHOW_NAME方法,因爲它是一個實例方法。我完全理解這一點。這本書然後拋出這個例子。

class Class 
    def add_accessor(accessor_name) 
    self.class_eval %Q{attr_accessor :#{accessor_name}} 
    end 
end 

class Person 
end 

person = Person.new 
Person.add_accessor :name #note the capital P 
Person.add_accessor :age  #capital P here too 

person.name = "Mikey" 
person.age = 30 

puts person.name 

並繼續說明你可以動態地將方法添加到類中。我不明白的是,爲什麼當方法本身沒有被定義爲這樣的時候,我突然被允許將「add_accessor」方法稱爲類方法(使用大寫字母P)我認爲所有的類方法都必須這樣聲明?

class Math 
    def self.PI 
    3.141 
    end 
end 

puts Math.PI 

有人能夠啓發我嗎?

回答

1

看看這個:

person.instance_of?(Person) #=> true 
Person.instance_of?(Class) #=> true 

您已經定義了一個實例方法add_accessor該類Class的所有實例,因此Person類可以使用該方法,因爲它是Class一個實例。

我建議你看看metaprogramming和Ruby對象模型。

很好,這有助於

1

你擴展Class類,並且所有的類,像Person,是Class實例(沒錯,類是Class類的實例。他們是普通的對象)。

因此,當您撥打Person.add_accessor時,您正在調用實例方法Class#add_accessor

+0

介意。正式。嗚呼哀哉! –

0

因爲Person(與大寫字母P)是Class類的一個實例。

2

Ruby類是像其他所有東西的對象。您的Person類實際上是類Class的一個對象,而Class繼承自Module Module。當您將一個方法添加到類Class作爲實例方法時,您正在爲所有類提供一種新方法。 如果您在Person中聲明瞭def,那麼在沒有對象的情況下將無法調用它。要添加類方法一類,但不是全部,你必須在前面加上自方法名稱或類的名稱:

class Person 
    def instance_method 
    end 
    def self.class_method 
    end 
    def Person.other_class_method 
    end 
end 

在聲明方法self.class_method您聲明你的方法是一個單方法在類對象上。 self在類或模塊聲明中引用類對象,這就是爲什麼self.Person.是相同的。 在處理Ruby時,只記得的一切是一個對象,一切都有方法。 Ruby中也沒有函數,儘管相反。方法和對象,總是。