2012-01-30 9 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 

धन्यवाद

पी एस क्या अंतर है। टैस ने उत्तर दिया कि इस उदाहरण में, सिंगलटन_क्लास प्रत्येक नई ऑब्जेक्ट के लिए एक अलग ऑब्जेक्ट_आईडी वापस कर देगा, क्योंकि सिंगलटन_क्लास केवल एक ऑब्जेक्ट से संबंधित है। लेकिन आईआरबी शो अगले

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

मुझे कोई कार्यात्मक अंतर नहीं मिल रहा है, लेकिन मुझे लगता है कि एक होना चाहिए। –

+2

@JakubHampl, ऐसा लगता है कि मुझे अंतर मिला) –

+1

@AlexKliuchnikau मुझे पता था कि कोई होगा। आपको +1 –

उत्तर

10

इन T वर्गों के उदाहरण के बीच अंतर विधि देखने एल्गोरिथ्म में है: विधि हमेशा सिंगलटन वर्ग (और इसके मॉड्यूल) में खोजा गया है और केवल तभी इसे यहाँ नहीं पाया जाता है, यह कक्षा में खोजा गया है

इसका मतलब यह है कि हम प्रारंभ के बाद वर्ग T के पहले कार्यान्वयन करने के लिए विधि test जोड़ने अगर हम से जब हम कक्षा 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

+0

एक व्यावहारिक दृष्टिकोण से, आप दूसरे पर एक कब करेंगे? – Claw

+0

@ क्लाउ, उपरोक्त विधियां केवल उत्सुक परीक्षण नमूने हैं, मैं इस तरह कुछ भी वास्तविक वर्ग के प्रारंभकर्ता में नहीं लिखूंगा। आम तौर पर: कक्षा के * सभी * उदाहरणों में विधि जोड़ने की आवश्यकता होने पर * कक्षा * में विधियों को जोड़ें और जब आपको कक्षा के * एकल * उदाहरण में विधि जोड़ने की आवश्यकता होती है तो * सिंगलटन कक्षा * में विधि जोड़ें। उदाहरण के लिए 2 ओपी * प्रत्येक * विधि उदाहरण (प्रारंभकर्ता में) * सिंगलटन वर्ग * में विधि जोड़ता है - यह व्यावहारिक नहीं है, ऐसी स्थितियों में * कक्षा * में विधि जोड़ें। –

7

singleton_class आप Class कि उस वस्तु के लिए अद्वितीय है देता है। self.class आपको कक्षा देता है कि Class शेयर की सभी ऑब्जेक्ट्स। क्योंकि एक singleton_class केवल एक Object के अंतर्गत आता है 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 वापस आ जाएगी। self.class वही लौटाएगा क्योंकि self.class हर बार उसी Class पर इंगित करता है।

+2

जो दस्तावेज़ों से बहुत अधिक सीधे अनुसरण करता है। लेकिन यह सवाल का जवाब नहीं है। उपरोक्त कोड में वास्तव में दो दृष्टिकोण क्या अंतर करते हैं? –

+1

ऐसा लगता है कि ओपी कक्षा और सिंगलटन वर्ग के बीच क्या अंतर नहीं है, लेकिन कार्यक्रम निष्पादन बिंदु से प्रदान किए गए इन दो उदाहरणों के बीच क्या अंतर है। दोनों मामलों में 'टी' के उदाहरणों में विधि 'परीक्षण' के साथ उदाहरण होगा, और वे अलग कैसे हैं? –

+0

प्रतिक्रिया के लिए धन्यवाद, एलेक्स, निश्चित रूप से, मैं – Fivell