2012-04-17 21 views
186

Ruby docs for dup कहते हैं:रुबी के डुप्लिक और क्लोन विधियों के बीच क्या अंतर है?

सामान्य तौर पर, clone और dup वंशज कक्षाओं में विभिन्न अर्थ विज्ञान हो सकता है। जबकि clone का उपयोग किसी ऑब्जेक्ट को डुप्लिकेट करने के लिए किया जाता है, जिसमें आंतरिक स्थिति, dup आमतौर पर नया उदाहरण बनाने के लिए वंशज ऑब्जेक्ट की कक्षा का उपयोग करता है।

लेकिन वे वास्तव में एक ही कर रहे हैं जब मैं कुछ परीक्षण मैंने पाया कार्य करें:

class Test 
    attr_accessor :x 
end 

x = Test.new 
x.x = 7 
y = x.dup 
z = x.clone 
y.x => 7 
z.x => 7 

तो दो तरीकों के बीच मतभेद क्या हैं?

+26

मैं मैं में केवल अंतर नहीं पता था कि इच्छा * क्या * 'dup' और' clone' करता है, लेकिन * * आप एक का उपयोग क्यों चाहते हैं दूसरे की बजाय। –

+1

यहां एक अच्छा लिंक भी है - https://coderwall.com/p/1zflyg –

उत्तर

262

उप-वर्ग विभिन्न विध्वंस प्रदान करने के लिए इन विधियों को ओवरराइड कर सकते हैं। Object में, दो महत्वपूर्ण अंतर हैं।

पहला, clone सिंगलटन वर्ग की प्रतिलिपि बनाता है, जबकि dup नहीं करता है।

o = Object.new 
def o.foo 
    42 
end 

o.dup.foo # raises NoMethodError 
o.clone.foo # returns 42 

दूसरा, clone, जमे हुए राज्य को बरकरार रखता है, जबकि dup नहीं करता है।

class Foo 
    attr_accessor :bar 
end 
o = Foo.new 
o.freeze 

o.dup.bar = 10 # succeeds 
o.clone.bar = 10 # raises RuntimeError 

Rubinius implementation for these methods अक्सर इन सवालों के जवाब के लिए अपने स्रोत है, क्योंकि यह काफी स्पष्ट है, और एक काफी आज्ञाकारी रूबी कार्यान्वयन है।

+13

यदि कोई इसे फिर से बदलने की कोशिश करता है: "सिंगलटन क्लास", जो रूबी में एक अच्छी तरह से परिभाषित शब्द है, न केवल सिंगलटन * विधियों *, बल्कि सिंगलटन कक्षा पर परिभाषित किसी भी स्थिरांक भी शामिल है। विचार करें: 'ओ = ऑब्जेक्ट.न्यू; कक्षा << ओ; एक = 5; समाप्त; रखता है (वर्ग << o.clone; ए; अंत); रखता है (वर्ग << o.dup; ए; अंत) '। –

+1

महान उत्तर के बाद, एक महान टिप्पणी के बाद, लेकिन यह मुझे सिंटेक्स को समझने के लिए एक जंगली हंस पीछा का नेतृत्व किया। यह किसी और की मदद करेगा जो भ्रमित भी हो सकता है: http://www.devalot.com/articles/2008/09/ruby-singleton – davidpm4

+1

मुझे लगता है कि "सिंगलटन क्लास" में यह भी उल्लेखनीय है कि इसमें कोई भी मॉड्यूल शामिल है मूल वस्तु पर 'विस्तारित' किया गया है। तो 'Object.new.extend (संख्यात्मक) .dup.is_a? (संख्यात्मक)' झूठी वापसी करता है। – Daniel

28

एक अंतर जमे हुए वस्तुओं के साथ है। जमे हुए ऑब्जेक्ट के clone भी जमे हुए हैं (जबकि एक जमे हुए ऑब्जेक्ट का dup नहीं है)।

class Test 
    attr_accessor :x 
end 
x = Test.new 
x.x = 7 
x.freeze 
y = x.dup 
z = x.clone 
y.x = 5 => 5 
z.x = 5 => TypeError: can't modify frozen object 

सिंगलटन विधियों के साथ एक और अंतर है। यहां वही कहानी, dup उनको कॉपी नहीं करता है, लेकिन clone करता है।

def x.cool_method 
    puts "Goodbye Space!" 
end 
y = x.dup 
z = x.clone 
y.cool_method => NoMethodError: undefined method `cool_method' 
z.cool_method => Goodbye Space! 
+0

यह मेरे लिए बहुत उपयोगी था। यदि आप जमे हुए स्थिर मूल्य बना रहे हैं और इसे इस तरह से पास कर रहे हैं: https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L248 (रेल कुकी हैंडलिंग) तो आप कर सकते हैं आसानी से एक त्रुटि प्राप्त करें जब वे आपको अनजान करते हैं तो वे इसे क्लोन करते हैं और फिर क्लोन को संशोधित करने का प्रयास करते हैं। अपने जमे हुए मूल्य को डुप्लिकेट करना और उसमें गुजरने से आप कम से कम गारंटी दे सकते हैं कि कोई भी यहां रैक तोड़ने के बिना गलती से आपके स्थिर को संशोधित करता है। – XP84

151

जब ActiveRecord के साथ काम भी एक महत्वपूर्ण अंतर नहीं है:

dup अपने आईडी के बिना एक नई वस्तु स्थापित किया जा रहा बनाता है, इसलिए आप .save

category2 = category.dup 
#=> #<Category id: nil, name: "Favorites"> 

clone मारकर डेटाबेस के लिए एक नई वस्तु को बचा सकता है एक ही आईडी के साथ एक नई वस्तु बनाता है, इसलिए उस नए ऑब्जेक्ट में किए गए सभी परिवर्तन मूल रिकॉर्ड को ओवरराइट करेंगे यदि .save

category2 = category.clone 
#=> #<Category id: 1, name: "Favorites"> 
+35

यह उत्तर वह है जिसकी आईएमओ सबसे महत्वपूर्ण व्यावहारिक जानकारी है ... अन्य उत्तर एसोटेरिका पर रहते हैं, जबकि यह उत्तर एक महत्वपूर्ण व्यावहारिक अंतर को इंगित करता है। – jpwynn

+26

उपरोक्त ActiveRecord के लिए विशिष्ट है; मानक रूबी में भेद कहीं अधिक सूक्ष्म है। – ahmacleod

+1

@Stefan और @jvalanen: जब मैं अपने 'ActiveRecord' ऑब्जेक्ट पर' डुप्ली 'और' क्लोन 'विधियों को लागू कर रहा हूं, तो मुझे उत्तर में जो बताया गया है उसके विपरीत परिणाम मिल रहे हैं। जिसका अर्थ है कि जब मैं 'dup' का उपयोग कर रहा हूं, तो यह 'id' सेट होने के साथ एक नया ऑब्जेक्ट बनाता है और' क्लोन 'का उपयोग करते समय यह किसी आईडी को सेट किए बिना ऑब्जेक्ट बनाता है। क्या आप इसे फिर से देख सकते हैं और साफ़ कर सकते हैं? । Thnx –

2

दोनों लगभग समान हैं लेकिन क्लोन डुप्लिकेट से एक और चीज करता है। क्लोन में, वस्तु की जमे हुए स्थिति भी कॉपी की जाती है। डुप्लिक में, यह हमेशा thawed होगा।

f = 'Frozen'.freeze 
    => "Frozen" 
f.frozen? 
    => true 
f.clone.frozen? 
    => true 
f.dup.frozen? 
    => false 
3

newer doc एक अच्छा उदाहरण में शामिल हैं:

class Klass 
    attr_accessor :str 
end 

module Foo 
    def foo; 'foo'; end 
end 

s1 = Klass.new #=> #<Klass:0x401b3a38> 
s1.extend(Foo) #=> #<Klass:0x401b3a38> 
s1.foo #=> "foo" 

s2 = s1.clone #=> #<Klass:0x401b3a38> 
s2.foo #=> "foo" 

s3 = s1.dup #=> #<Klass:0x401b3a38> 
s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401b3a38>