2012-01-01 113 views
5

受此article的啓發,我在玩Ruby方法調用層次結構並注意到一些奇怪的事情。Ruby方法調用層次結構

考慮:

class B 
    def foo 
    "- Instance method defined by B" 
    end 

    def method_missing(method) 
    puts "- method_missing (#{method}) on b. Redirecting to b.foo\n" 
    foo 
    end 
end 

b = B.new 

def b.foo 
    "- Method defined directly on an instance of B\n" + super 
end 

def b.method_missing(method) 
    "- method_missing (#{method}) on b. Calling super\n" + super 
end 

puts "Calling 'bar' on b of type #{b.class}:" 
puts b.bar 

運行它給:

Calling 'bar' on b of type B: 
- method_missing (bar) on b. Redeirecting to b.foo 
- method_missing (bar) on b. Calling super 
- Method defined directly on an instance of B 
- instance method defined by B 

我的問題是:

由於我打電話b.bar(在對象上),怎麼來的類的實例方法在調用objet的實例方法之前調用?

我本來期望b.method_missing(method)首先被調用,然後類的實例method_missing(method)(因爲我調用超?但超是類層次結構...),其中不重定向從barfoo。 另外,爲什麼在重定向到foo之後,實例的missing_method被調用?我們被告知我們正在重定向...

我想我不明白Ruby如何允許在一個類的實例(新對我)中定義實例方法的概念,而不是將其定義爲類的實例方法(經典語言)。

我希望這個問題是有道理的,也許我的頭仍然是從昨晚紡...

+1

我的返回值一起輸出在b.method_missing字符串看到的第一線刪除不相關的代碼,使問題更加明顯。提供一個* minimal *問題的例子通常是一個好主意。 – 2012-01-02 00:11:21

回答

4

的問題是,你的輸出並不反映執行的實際順序。讓我們來看看輸出:

method_missing (bar) on b. Redeirecting to b.foo 
method_missing (bar) on b. Calling super 

乍一看,這給人的印象是B#method_missing是單身方法b.method_missing這引起了你所描述的兩個問題之前調用。實際上,b.method_missing被正確地稱爲第一個。如果你看一下聲明puts b.bar如何評價這得到明確:

  1. b沒有方法bar,所以b.method_missing被調用帶有字符串'bar'作爲參數。
  2. b.method_missing依次通過使用super關鍵字調用方法B#method_missing
  3. B#method_missing使用puts到輸出上述
  4. 單身方法b.foo
  5. 最外puts執行被調用,這與b.foo
+2

+1;打敗了我。 – 2012-01-02 00:09:17

+0

Niklas,謝謝澄清(並刪除不相關的代碼)。謝謝您的回答! – dynex 2012-01-02 06:01:03

+0

在調試器中運行它當然可以澄清它。我應該做到這一點 - 對不起,我感謝你的耐心。 – dynex 2012-01-02 06:22:22