2012-12-06 41 views
10

爲什麼在下面的代碼片段foo替換其定義?爲什麼foo不是零 - 或功能內功能

def foo 
    def foo 
    1 
    end 
end 

首次foo爲零

foo 
=> nil 

foo.foo 
=> 1 

現在,如果我再打電話foo

foo 
=> 1 

正如你所看到foo不爲零了。誰可以給我解釋一下這個?謝謝。

回答

6
def foo 
    p "about to redef foo" 
    def foo 
    1 
    end 
end 
foo 
"about to redef foo" 
=> nil 
foo 
=> 1 

而且,當你調用foo.foo,好像你正在試圖訪問內foo方法,但它並沒有這樣的。您的foo方法實際上定義在Object上,所以您實際上呼叫1.foo

0

當您第一次調用foo返回方法foo,當你再次調用foo則返回1 讀closure

+0

實際上它第一次返回nil,b/c Ruby不支持第一類方法(至少在這個意義上)。所以沒有方法對象返回。 – trans

1

如果你想要這個效果,嘗試

def foo 
    foo = proc { 
    1 
    } 
end 

由於def方法不創建一個新的self。每種方法都綁定爲 至self,在這種情況下爲main,Object.new爲 實例化爲由ruby解釋器加載的每個文件。在 類中,self是類,並且您將獲得實例方法。

+0

分配不是必需的。 – akuhn

+0

他希望foo在另一個命名空間中,但是,該函數只是返回一個塊。 – Reactormonk

1

讀取時解析方法定義,但在調用之前不會執行。當執行所述第一foo,最外面的foo被執行,其定義如Object#foo

def foo 
    1 
end 

和作爲所定義的方法的操作的返回值返回nil。從那時起,當你調用foo,在執行時,返回的紅寶石

1 
0

嵌套方法的定義是混亂的新定義foo

它們實際上是重新定義!

會發生什麼是兩個定義適用於最外面的背景。這兩個定義都定義了相同的(!)方法foo。雖然外部定義在讀取文件時被解釋,而內部定義僅在第一次調用外部方法時被解釋。它將取代最初的定義。

鑑於這種代碼

def foo 
    def foo 
    1 
    end 
end 

讓我們通過這樣的:

加載文件一個全球性的方法 foo
  1. 與身體def foo; 1; end定義。
  2. ,當你調用foo()執行這一全球方法和重新定義全局法foo與身體1,並返回nil自定義一個方法沒有返回值。

    當你調用
  3. foo().foo()執行了全局方法,並返回1,在其上再次執行全局法,再次返回1

這裏混淆兩件事情,a)該嵌套方法定義既適用於相同外範圍以及b),一個全局方法可以在任何對象上調用。

下面是另一個演示嵌套定義是如何重新定義的例子。

class A 
    def m(arg=nil) 
    def m; 42; end if arg 
    23 
    end 
end 

這裏發生了什麼

a = A.new 
a.m # => 23 
a.m # => 23 
a.m(:magic) # => 23 
a.m # => 42 
a.m # => 42 

,你可以看到,嵌套定義實際上是一個重新定義。

0

就我個人而言,我一直認爲它非常奇怪,它定義了班級上的內部def。我認爲在單身人士上定義它會更明智。例如相當於def self.foo,因爲它是在實例級而不是級別級調用的。

要麼是這樣,要麼只能從它所定義的方法中調用 - 雖然這可能沒有用處,因爲我們有lambda表達式。

但有一點是肯定的,但在實踐中你幾乎從不會看到這一點。