2012-01-30 28 views
10

有什麼區別,當我做紅寶石self.class.class_eval或singleton_class.class_eval

class T 

    def initialize 
    self.class.class_eval do 
     def test 
     return self.class.object_id 
    end 
    end 
    end 

end 

class T 

    def initialize 
    singleton_class.class_eval do 
     def test 
     return self.class.object_id 
    end 
    end 
    end 

end 

感謝

PS。 Tass回答說,在這個例子中,singleton_class將爲每個新對象返回一個不同的object_id,因爲singleton_class只屬於一個對象。但是,IRB顯示未來

1.9.2p180 :001 > class T 
1.9.2p180 :002?> 
1.9.2p180 :003 >  def initialize 
1.9.2p180 :004?>  singleton_class.class_eval do 
1.9.2p180 :005 >    def test 
1.9.2p180 :006?>     return self.class.object_id 
1.9.2p180 :007?>    end 
1.9.2p180 :008?>  end 
1.9.2p180 :009?>  end 
1.9.2p180 :010?> 
1.9.2p180 :011 >  end 
=> nil 
1.9.2p180 :012 > t = T.new 
=> #<T:0x00000100ae9cb8> 
1.9.2p180 :013 > t1 = T.new 
=> #<T:0x00000100ad7ef0> 
1.9.2p180 :014 > t1.test == t.test 
=> true 
1.9.2p180 :015 > t1.test 
=> 2153233300 
1.9.2p180 :016 > t.test 
=> 2153233300 
1.9.2p180 :017 > 
+1

我找不到任何功能差異,但我認爲應該有一個。 – 2012-01-30 16:23:47

+2

@JakubHampl,看起來像我發現的區別) – 2012-01-30 17:35:24

+1

@AlexKliuchnikau我知道有人會。 +1給你! – 2012-01-30 22:35:47

回答

10

這些T類的實例之間的區別在於在該方法中查找算法:方法總是在單例類(及其模塊)搜索並僅在這裏沒有發現它,則搜索在

這意味着如果我們添加方法test到初始化後的第一個實施T類的,我們會得到不同的結果比我們做同樣的第二實施T類:

# First example 
class T 
    def initialize 
    self.class.class_eval do 
     def test 
     return self.class.object_id 
     end 
    end 
    end 
end 

t = T.new 

class T 
    def test 
    'overriden' 
    end 
end 

puts t.test # => 'overriden' 

class T 
    def initialize 
    singleton_class.class_eval do 
     def test 
     return self.class.object_id 
     end 
    end 
    end 
end 

t = T.new 

class T 
    def test 
    'overriden' 
    end 
end 

puts t.test # => 77697390 
+0

感謝您的迴應!現在我看到了不同) – Fivell 2012-01-30 17:25:23

+0

從實際的角度來看,你會什麼時候做一個呢? – Claw 2012-01-31 01:44:03

+0

@Claw,上面的方法只是好奇的測試樣本,我不會在真實類的初始化器中寫這樣的東西。通常:當需要將方法添加到類的所有實例並將方法添加到單例類時,將方法添加到*類*中,當需要將方法添加到類的單個*實例時。在示例2中,OP將方法添加到每個*方法實例的* singleton類*(在初始化程序中) - 這是不實用的,在這種情況下爲* class *添加方法。 – 2012-01-31 10:35:28

7

singleton_class給你Class是唯一到該對象。 self.class給你所有對象Class分享。 Example

foobar = Array.new 

# this defines a method on the singleton class 
def foobar.size 
    "Hello World!" 
end 

foobar.size # => "Hello World!" 
foobar.class # => Array 

bizbat = Array.new 
bizbat.size # => 0 

在上面的例子,singleton_class將返回不同object_id爲每個新的對象,因爲一個singleton_class只能屬於一個Objectself.class將返回相同的,因爲self.class每次都指向相同的Class

+2

這幾乎直接來自文檔。但這不是問題的答案。這兩種方法實際上在上面的代碼中有什麼不同? – 2012-01-30 16:22:50

+1

看起來像OP並沒有問及類和單例類之間的差別,但是他從程序執行的角度提供的這兩個例子之間有什麼區別。在這兩種情況下,'T'的實例都會有方法爲'test'的實例,它們又有什麼不同? – 2012-01-30 16:58:07

+0

感謝您的迴應,亞歷克斯,當然,我想了解你提到的差異 – Fivell 2012-01-30 17:01:42