2009-11-08 106 views
5

這個問題有兩個部分。擴展類和實例

在Ruby編程語言手冊中,有一個使用模塊擴展字符串對象和類的示例(第8.1.1節)。

第一個問題。爲什麼如果你用新方法擴展一個類,然後創建該類的對象/實例,那麼你不能訪問該方法?

irb(main):001:0> module Greeter; def ciao; "Ciao!"; end; end 
=> nil 
irb(main):002:0> String.extend(Greeter) 
=> String 
irb(main):003:0> String.ciao 
=> "Ciao!" 
irb(main):004:0> x = "foo bar" 
=> "foo bar" 
irb(main):005:0> x.ciao 
NoMethodError: undefined method `ciao' for "foo bar":String 
     from (irb):5 
     from :0 
irb(main):006:0> 

第二部分,當我嘗試擴展Fixnum對象時,出現未定義的方法錯誤。有人可以解釋爲什麼這適用於字符串,但不是fixnum?

irb(main):045:0> module Greeter; def ciao; "Ciao!"; end; end 
=> nil 
irb(main):006:0> 3.extend(Greeter) 
TypeError: can't define singleton 
     from (irb):6:in `extend_object' 
     from (irb):6:in `extend' 
     from (irb):6 

回答

9

第一個問題。爲什麼如果 使用新方法擴展一個類,然後 然後創建該類的對象/實例,那麼您無法訪問該方法?

因爲您擴展了String類,所以#ciao是一個類方法而不是實例方法。

String.send(:include, Greeter) 
x = "foo bar" 
x.ciao 
# => "Ciao!" 

第二部分,當我嘗試擴展 Fixnum對象對象,我得到一個未定義的 方法錯誤。有人可以解釋爲什麼 這適用於字符串,但不適用於 fixnum?

這是short answer

「Fixnums,符號,真實的,零和 假作爲即時 值來實現。即日值, 變量保存對象本身, 而不是對它們的引用。

辛格爾頓方法不能定義爲 這樣的對象。相同的值的兩個Fixnum總是表示相同的 對象實例,因此(例如) Fixnum的實例變量與 值「1」在所有之間共享這個「ones」就是這個系統。這使得 不可能定義一個單 方法只是其中之一。」

關過程中,您可以包括/ EXTEN的Fixnum對象類,每Fixnum對象實例會暴露在密新的方法。 這是正是Rails的/不的ActiveSupport爲了讓你寫

3.days.ago 
1.hour.from_now 
+0

你回答第一部分沒有解釋(對我)的原因。在其他語言中,當您更改類並創建該類類型的新對象時,您將獲得新方法。我假定從類到對象的連接是無效的。你能解釋爲什麼這個連接在這裏無效嗎? – teleball 2009-11-08 18:00:31

+0

研究「包括」你給了我幫助。所以,現在看起來我明白擴展和包含之間存在差異,現在知道要搜索什麼,這裏有一篇文章解釋了這些差異:http://stackoverflow.com/questions/156362/what-是最差之間-包括和 - 延長功能於紅寶石 – teleball 2009-11-08 18:10:09

2

obj.extend(module)增加在module所有方法obj。當被稱爲String.extend(Greeter)你是從Greeter添加方法TH代表StringClass的實例。

將其他實例方法添加到現有類最簡單的方法是重新打開該類。下面的例子做同樣的事情:

class String 
    include Greeter 
end 

class String 
    def ciao 
    "Ciao!" 
    end 
end 

Fixnums(以及符號,真實,虛假,無)以不同的方式,以正常情況下的處理方式。具有相同值的兩個Fixnum將始終由相同的對象實例表示。因此,Ruby不允許你擴展它們。

你當然也可以擴展任何其他類的實例,例如:

t = "Test" 
t.extend(Greeter) 
t.ciao 
=> "Ciao!"