2009-09-13 14 views
8

रुबी #cloneऑब्जेक्ट में परिभाषित करता है। मेरी प्राप्ति के लिए, कुछ वर्ग इसे कॉल करते समय अपवाद उठाते हैं। मैं NilClass, TrueClass, FalseClass, Fixnum पाया इस व्यवहार कर रहे हैं।कौन सा रूबी वर्ग समर्थन करता है। क्लोन?

1) क्या कक्षाओं (कम से कम कोर-क्लास) की पूरी सूची मौजूद है, जो #clone की अनुमति नहीं देती है? या यह पता लगाने का कोई तरीका है कि कोई विशिष्ट वर्ग #clone का समर्थन करता है या नहीं?

2) 42.clone के साथ क्या गलत है?

+2

मैं वास्तव में जानना चाहते हैं कि एक वर्ग अपने आप को cloneable है आप कैसे परीक्षण करना चाहते हैं। ऐसा लगता है कि एक वर्ग खुद को क्लोन करने की अनुमति नहीं देना चाहता है, तो उसे ऑब्जेक्ट से प्राप्त क्लोन विधि को निजी बनाना चाहिए ताकि आप केवल अपने अस्तित्व के लिए public_methods के अंतर्गत परीक्षण कर सकें। मुझे सामान्य ज्ञान की तरह लगता है। –

उत्तर

7

मुझे नहीं लगता कि औपचारिक सूची है, कम से कम जब तक आप स्रोत को पढ़ने की गणना नहीं करते हैं। कारण 2) काम नहीं करता है फिक्सनम्स पर लागू अनुकूलन के कारण है। वे आंतरिक रूप से उनके वास्तविक मूल्यों के रूप में संग्रहीत/पारित होते हैं (इसलिए सत्य, झूठे और शून्य हैं), और पॉइंटर्स के रूप में नहीं। बेवकूफ समाधान सिर्फ 42.clone है, उसी 42 पर लौटें, लेकिन फिर invariant obj.clone.object_id != obj.object_id अब नहीं होगा, 42.clone वास्तव में क्लोनिंग नहीं होगा।

+0

'obj.clone.object_id! = Obj.object_id' सत्य और' obj। clone.object_id == obj.object_id 'हमेशा सत्य नहीं है अलग हैं। कि पूर्व धारण नहीं करता है इसका मतलब यह नहीं है कि उत्तरार्द्ध नहीं करता है। – sawa

0

आप अपरिवर्तनीय कक्षाओं को क्लोन नहीं कर सकते हैं। अर्थात। आपके पास ऑब्जेक्ट 42 (फिक्सम के रूप में) का केवल एक उदाहरण हो सकता है, लेकिन "42" के कई उदाहरण हो सकते हैं (क्योंकि स्ट्रिंग म्यूटेबल है)। आप प्रतीकों को क्लोन नहीं कर सकते हैं क्योंकि वे अपरिवर्तनीय तारों की तरह कुछ हैं।

आप इसे आईआरबी में object_id विधि के साथ देख सकते हैं। (दोहराए गए कॉल के बाद प्रतीकों और फिक्समम्स आपको वही ऑब्जेक्ट_आईडी देंगे)

+1

उत्परिवर्तन के साथ इसका कोई लेना-देना नहीं है (वास्तव में, आप फिक्सनम में राज्य जोड़ सकते हैं)। – Chuck

+0

फिक्सनम के लिए वास्तव में विचित्र डिफ़ॉल्ट व्यवहार, विशेष रूप से यह देखते हुए कि इसमें क्लोन विधि है, d.class.method_defined? (: क्लोन) == सच –

5

फ़िक्सम एक विशेष श्रेणी है जिसे भाषा द्वारा विशेष उपचार दिया जाता है। जब तक आपका प्रोग्राम लॉन्च होता है, कक्षा के प्रत्येक नंबर के लिए सटीक एक फिक्सम है, और उन्हें एक विशेष प्रतिनिधित्व दिया जाता है जो कोई अतिरिक्त जगह नहीं लेता - इस तरह, मूल गणित संचालन आवंटित नहीं होते हैं और हटाए जाते हैं पागल की तरह स्मृति। इस वजह से, एक से अधिक 42 नहीं हो सकते हैं।

दूसरों के लिए, उनके सभी में एक बात आम है: वे सिंगलेट हैं। परिभाषा के अनुसार सिंगलटन वर्ग का केवल एक उदाहरण है, इसलिए इसे क्लोन करने का प्रयास करना एक त्रुटि है।

+1

"इस वजह से, एक से अधिक 42 नहीं हो सकते हैं।" और क्यों होना चाहिए? यह एकदम सही है। –

1

मैं अभी भी ठीक से clonability के लिए परीक्षण करने के लिए कैसे पता नहीं, लेकिन यहाँ त्रुटि फँसाने का उपयोग कर clonablity के लिए परीक्षण करने के लिए एक बहुत ही भद्दा, बुराई तरीका है:

def clonable?(value) 
    begin 
    clone = value.clone 
    true 
    rescue 
    false 
    end 
end 

और यहाँ कैसे आप भी कर सकते हैं क्लोन unclonable है। कम से कम बहुत कम कक्षाओं के लिए मैंने इसे थक दिया है।

b = :b 
puts "clonable? #{clonable? b}" 

b = proc { b == "b" } 
puts "clonable? #{clonable? b}" 

b = [:a, :b, :c] 
c = super_mega_clone(b) 

puts "c: #{c.object_id}" 
puts "b: #{b.object_id}" 
puts "b == c => #{b == c}" 
b.each_with_index do |value, index| 
    puts "[#{index}] b: #{b[index].object_id} c: #{c[index].object_id}" 
end 
b[0] = :z 

puts "b == c => #{b == c}" 
b.each_with_index do |value, index| 
    puts "[#{index}] b: #{b[index].object_id} c: #{c[index].object_id}" 
end 

b = :a 
c = super_mega_clone(b) 
puts "b: #{b.object_id} c: #{c.object_id}" 

> clonable? false 
> clonable? true 
> c: 2153757040 
> b: 2153757480 
> b == c => true 
> [0] b: 255528 c: 255528 
> [1] b: 255688 c: 255688 
> [2] b: 374568 c: 374568 
> b == c => false 
> [0] b: 1023528 c: 255528 
> [1] b: 255688 c: 255688 
> [2] b: 374568 c: 374568 
> b: 255528 c: 255528 
1

मैं YARV के स्रोत कोड के एक git grep "can't clone", और

lib/singleton.rb: raise TypeError, "can't clone instance of singleton #{self.class}" 
object.c:  rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj)); 
test/test_singleton.rb: expected = "can't clone instance of singleton TestSingleton::SingletonTest" 

पहले और तीसरे लाइनों मिला संकेत मिलता है कि आप एक सिंगलटन क्लोन नहीं कर सकते हैं:

def super_mega_clone(value) 
    eval(value.inspect) 
end 

यहाँ कुछ नमूना परीक्षण है ।

दूसरी पंक्ति rb_special_const_p(obj) को संदर्भित करती है। लेकिन यह मेरे केन से आगे जा रहा है।

0

रेल आपके द्वारा "डुप्लिकेबल?()" विधि के साथ वर्णित कक्षाओं का विस्तार करने के लिए प्रतीत होता है।

http://api.rubyonrails.org/files/activesupport/lib/active_support/core_ext/object/duplicable_rb.html

+0

डुप्लिकेशनल?() को ActiveSupport मणि में भी परिभाषित किया गया है –

संबंधित मुद्दे