2011-10-25 7 views
14

में पहचान द्वारा वस्तुओं की तुलना करने के लिए गारंटीकृत तरीका रुबी में उनकी पहचान से दो वस्तुओं की तुलना करने की गारंटीकृत तरीका क्या है? दो चर दिए गए, मैं चर वापस लौटना चाहता हूं अगर चर स्मृति में सटीक उसी वस्तु को इंगित करते हैं।रुबी

सबसे रूबी वस्तुओं के लिए, equal? विधि पहचान द्वारा तुलना:

f = g = Object.new 
p f.equal? g # => true 

बहरहाल, यह सभी वस्तुओं के लिए काम नहीं करता। उदाहरण के लिए:

class F 
    def ==(obj) false end 
    def ===(obj) false end 
    def eql?(obj) false end 
    def equal?(obj) false end 
    def object_id; self end 
end 

f = g = F.new 
p f == g  # => false 
p f === g  # => false 
p f.eql? g  # => false 
p f.equal? g # => false 
p f.object_id == g.object_id # => false 

क्या एक सरल/पहचान द्वारा दो वस्तुओं की तुलना में इसकी गारंटी रास्ता हार जाता है जो नहीं किया जा सकता?

यह एक विशुद्ध रूप से बौद्धिक प्रश्न है। "क्यों" से शुरू होने वाले किसी भी प्रश्न का उत्तर शायद "क्योंकि मैं उत्सुक हूं।"

+0

कंप्यूटर विज्ञान और गणित में चीजों के लिए शब्द क्या है? इसके लिए कुछ शब्द है। मैं "शैतानी" कहना चाहता हूं, लेकिन कम बुराई। –

+0

मुझे लगता है कि शब्द "गलत" है। जैसा कि, यह एक चीज नहीं है जो आपको करना चाहिए। – Chuck

+1

मैं एक शब्द का उपयोग करना चाहता हूं जो "एफ" से शुरू होता है ...जब तक आप सी एक्सटेंशन लिखना नहीं चाहते हैं, तब तक कोई गारंटी नहीं है, आपको विनम्र होना चाहिए लेकिन किसी को भी सामाजिक-सामाजिक सोसायपैथ होने से रोकना नहीं है। –

उत्तर

12

आप Object#object_id का एक अनबाउंड संस्करण ले सकते हैं, इसे प्रश्न में ऑब्जेक्ट से बांधें और देखें कि यह क्या कहता है।

class F 
    # ... 
    def inspect; 'pancakes!' end # Just so we can tell what we have later. 
end 

तब: एक अतिरिक्त के साथ अपने F वर्ग को देखते हुए

>> f = F.new 
>> f.object_id 
=> pancakes! 
>> unbound_object_id = Object.instance_method(:object_id) 
>> unbound_object_id.bind(f).call 
=> 2153000340 
>> ObjectSpace._id2ref(2153000340).inspect 
=> "pancakes!" 
बेशक

, अगर कोई वस्तु को खोलता है और object_id बदल देता है तो आप भाग्य से बाहर हो, लेकिन यह कम से कम हो जाएगा अपने अगर कोई ऐसा करता है तो समस्याएं। यदि आप किसी और चीज को लोड करने से पहले अपने unbound_object_idUnboundMethod को पकड़ सकते हैं, तो इससे कोई फर्क नहीं पड़ता कि कोई Object#object_id बदलता है क्योंकि unbound_object_id अभी भी मूल सही होगा।

तो इस दौर के बारे में हैक आपको किसी ऑब्जेक्ट (उपरोक्त चेतावनी के अधीन) के लिए विश्वसनीय object_id देता है। अब आप अपनी विश्वसनीय तुलना प्राप्त करने के लिए ऑब्जेक्ट आईडी को पकड़ और तुलना कर सकते हैं।

+0

बढ़िया, यह काम करता है! मैं सिर्फ एक फ़ंक्शन का योगदान करना चाहता हूं जो इस तकनीक का उपयोग पहचान द्वारा दो चर की तुलना करने के लिए करता है: 'def compar_by_identity (x, y); id = object.instance_method: object_id; id.bind (x) .call == id.bind (y) .call; अंत ' –

3

म्यू द्वारा जवाब बहुत छोटा महान है, लेकिन वहाँ एक और तरीका है आप हैश वर्ग की एक विशेष सुविधा का उपयोग कर ऐसा कर सकते हैं है:

def compare_by_identity(x, y) 
    h = {}.compare_by_identity 
    h[x] = 1 
    h[y] = 2 
    h.keys.size == 1 
end 

compare_by_identity सुविधा रूबी 1.9 में जोड़ा गया है। 2, तो यह फ़ंक्शन पिछले संस्करणों में काम नहीं करेगा। मुझे लगता है कि mu बहुत छोटा है का उत्तर बेहतर है।

4

BasicObject#equal? का उपयोग करें। Ruby documentation के अनुसार:

== के बराबर, बराबर? विधि को उप-वर्गों द्वारा कभी ओवरराइड नहीं किया जाना चाहिए: इसका उपयोग ऑब्जेक्ट पहचान निर्धारित करने के लिए किया जाता है (यानी, a.equal? ​​(बी) iff एक जैसा ही ऑब्जेक्ट है b)।

मजबूत गारंटी की आवश्यकता है? AFAIK इसे प्राप्त नहीं कर सकता, BaseObject#object_id, ObjectSpace._id2ref, Hash#compare_by_identity ओवररीन या बंदर भी पैच किया जा सकता है (कम से कम यह मेरी व्यक्तिगत धारणा है)।

+0

यदि आप पर्याप्त रूप से घृणास्पद रवैया रखते हैं तो आप अपना खुद का 'def बराबर' (अन्य) झूठा अंत 'कार्यान्वयन प्रदान कर सकते हैं। –