2010-12-10 40 views
26

我讀編程的Ruby 1.9的元編程節,我無法理解這是怎麼回事內部class_eval/class_execinstance_eval/instance_exec之間。Ruby的清晰度和instance_eval的對比class_eval

所以首先,我的理解是,def增加了一個方法的self方法表(類對象):

class A 
    puts self # => A 
    def foo; 42; end # added to the method table of self, so becomes an instance method 
end 
A.new.foo # => 42 

如果我們使用class_eval,我們得到了相同的行爲:

A.class_eval do 
    puts self # => A 
    def bar; 42; end # same as above 
end 
A.new.bar # => 42 

但不知何故,在instance_eval情況下,情況就不同了:

A.instance_eval do 
    puts self # => A 
    def baz; 42; end # added to the method table of an anonymous 
        # singleton class of self, so becomes a class method 
end 
puts A.baz # => 42 

s = 'string' 
s.instance_eval do ... end # same behavior, so now def creates an instance method 

因此,我瞭解class_evalinstance_eval之間的功能差異。

class_evalinstance_eval塊內的上下文看完全相同我也一樣 - 特別是self指向同一個對象,而local_variables是相同的。那麼塊(內部)內部發生什麼,使def的行爲有所不同?

是否有一些文件可以閱讀? instance_evalclass_eval的RDoc不起作用。看看源代碼,instance_eval似乎設置了一個singleton類對象,而class_eval沒有 - 但是這種區別在C代碼之外,在Ruby級別上是可見的嗎?

回答

31

我認爲你的困惑來自於def不依賴於當前自我的事實,你可能會認爲它是一個擁有自己規則的「當前階級」。

按照你的例子:

class A 
    # defs here go to A 
    puts self # => A 
    class << self 
    #defs here go to A's eigenclass 
    end 
end 

A.class_eval do 
    #defs here go to A 
end 

A.instance_eval do 
    #defs here go to A's eigenclass  
end 

s = "Hello World" 

class << s 
    #defs here go to s's eigenclass 
end 

下面是談論這個問題的章節的部分,它是相當明確的行爲

class_eval和instance_eval的都設置 自我的持續時間該塊。 然而,它們在 設置方法 定義的環境方面有所不同。 class_eval進行一些設置 ,如果你是在一個類 定義的身體,所以方法定義將 定義實例方法相反, 調用instance_eval的一類行爲 因爲如果你的 單例類自我的容器內工作。因此,您定義的任何方法將變爲 類方法。

我認爲唯一值得添加的是,您可以在任何對象中調用instance_eval,而不僅僅是類,行爲不會改變,但會產生不同的後果。

一些相關閱讀:

Ruby: instance_eval and class_eval method definitions

Chapter 4 of this most excelent series

+0

嗯,我明白了 - 這是有道理的。有什麼方法可以檢查Ruby代碼中的「當前類」嗎? – 2010-12-10 13:25:08

+1

我認爲在'A.instance_eval'中,你打算寫'#defs在這裏去A的本徵類?還是我誤會了? – 2010-12-10 13:33:27

+0

這並不簡單,我會在答案 – 2010-12-10 13:36:42

3

只需添加到@ krusty.ar的回答是:defdefine_method方法添加到當前方法定義背景(我相信這就是它叫,我不知道),而不是目前的self

它只是在模塊,類或單例類體內部,這兩個碰巧是一樣的。

但是,例如,在腳本主體(aka頂級)中,selfmain對象,但當前的方法定義上下文是Object