2012-04-20 16 views
7

यदि मैं माता-पिता और बाल वर्ग दोनों में equals() और hashCode() लागू करता हूं, तो super.equals() को equals() में बच्चे वर्ग में कॉल करना आवश्यक है, उदा।बाल वर्ग में super.equals और super.hashCode को कॉल करना?

public boolean equals(Object obj) { 

    if (obj.getClass() != ChildClass.class) { 
    return false; 
    } 

    return super.equals() && this.var == ((ChildClass) obj).var; 

} 
+0

पीएस मुझे लगता है कि अभिभावक वर्ग ऑब्जेक्ट नहीं है और 'बराबर' और 'हैशकोड' की सही परिभाषा दे रहा है। –

उत्तर

8

नहीं, यह आवश्यक नहीं है, और शायद गलत होगा। दरअसल, equal ओवरराइड करने के कारण का कारण यह है कि super.equals सही व्यवहार नहीं देता है (दाएं?)।

या super.equals सही व्यवहार देता है, तो आपको शायद एक और तरीका डालें, आपको शायद इसे ओवरराइड करने की परेशानी पर जाने की आवश्यकता नहीं है।

लेकिन यदि आप equals ओवरराइड कर रहे हैं, तो हाँ, आपको hashCode ओवरराइड करना होगा।

+2

'SuperClass.equals' स्पष्ट रूप से केवल 'सुपरक्लास' उदाहरणों की तुलना कर सकता है और' SubClass' के बारे में कुछ भी नहीं जानता है। यही कारण है कि 'सबक्लास' को इसे ओवरराइड करना चाहिए, भले ही यह 'सुपर क्लास' के संदर्भ में बिल्कुल सही है। लेकिन 'super.equals' (सबक्लास भागों की तुलना करने से पहले) को कॉल करने के बजाय 'सबक्लास' (या कई उप-वर्गों में से प्रत्येक में) अपने व्यवहार को फिर से लागू करना मूर्खतापूर्ण होगा, है ना? –

+4

ठीक है, यदि मूल्य समानता लागू की जा रही है, तो समानता के लिए चेक किए गए विरासत वाले फ़ील्ड प्राप्त करने के लिए 'super.equals()' को कॉल करना आवश्यक हो सकता है ... – Alan

+0

असल में, आपको कई बार केवल अतिरिक्त फ़ील्ड के लिए चेक जोड़ने की आवश्यकता होती है (जैसे @ एलन का उल्लेख है), इसलिए 'super.equals() 'को कॉल करना जरूरी है। इसके अतिरिक्त, यदि आप केवल फ़ील्ड जोड़ रहे हैं, तो आप 'हैशकोड()' को ओवरराइड करने के लिए _need_ नहीं करते हैं। – jtahlborn

2

अपने सुपर वर्ग बराबर लागू नहीं होता है, तो बुला super.equals आप वस्तु कार्यान्वयन जो केवल संदर्भ तुलना, इसलिए किसी भी सामान्य में कार्यान्वयन जहां आप एक व्यवसाय कुंजी यह वास्तव में होगा की तुलना करना चाहते बराबर होती है मिल जाएगा बहुत सारे झूठे नकारात्मक कारण बनते हैं।

यह कहा गया है कि वास्तव में उपरोक्त आपका कार्यान्वयन डिफ़ॉल्ट रूप से ऑब्जेक्ट में कार्यान्वयन के बराबर अलग नहीं है क्योंकि आप तुलना के लिए == का उपयोग कर रहे हैं।

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

0

संपादित

मैं सिर्फ क्या आपने देखा वर्ग समानता, नहीं instanceof इस्तेमाल किया - जिसका अर्थ है कि रिफ्लेक्सिविटी सही होगा। आपके उदाहरण में, super.equals का उपयोग शायद सही है, जब तक कि सुपरक्लस समानता की परिभाषा प्रदान नहीं करता है जो कि आपके उप-वर्ग की इच्छा है (उदाहरण के लिए Object करता है)।

मुख्य बिंदु यह है कि समानता की परिभाषा आपके वर्ग के पदानुक्रम में बिल्कुल एक प्रकार (कक्षा या इंटरफ़ेस) से आनी चाहिए। यदि उस परिभाषा के कार्यान्वयन में super.equals का लाभ होता है, तो यह ठीक है।

अंत संपादित, नीचे

मूल पाठ यह लगभग निश्चित रूप क्या करना गलत बात है, क्योंकि यह समानता के चिंतनशील संपत्ति का उल्लंघन होगा।

मान लीजिए कि आपके पास एक आकार है, और यह एक और आकार के बराबर है यदि वे एक ही प्रकार के हैं: स्क्वायर स्क्वायर बराबर है, सर्किल सर्किल के बराबर है, आदि। अब आप इसे रंगीन स्क्वायर बनाने के लिए बढ़ाते हैं जो रंगीन जांच जोड़ता है।

Shape shape1 = new Shape(SQUARE); 
Shape shape2 = new ColoredShape(SQUARE, RED); 

आप super.equals(other) && other.color == this.color रूप ColoredSquare.equals लागू, आपके सवाल में के रूप में। लेकिन अब, ध्यान दें कि shape1.equals(shape2) == true (shape1 के बाद से Shape.equals का उपयोग करता है), लेकिन shape2.equals(shape1) == false (क्योंकि यह रंग जांच जोड़ता है)।

कहानी का नैतिक यह है कि इस प्रकार की कैस्केडिंग समानता का उपयोग करना वास्तव में कठिन है, अगर असंभव नहीं है। असल में, समानता आपके प्रकार के पदानुक्रम के भीतर बिल्कुल एक प्रकार से आनी चाहिए - चाहे वह Object हो, चाहे आपका प्रकार, एक सुपर टाइप, या कुछ इंटरफ़ेस जो अनुबंध को परिभाषित करता है (उदाहरण के लिए संग्रह ढांचे में, जो Set, List आदि के लिए समानता को परिभाषित करता है।)।

+0

कहानी का नैतिक यह है कि आपको केवल ठोस वर्गों से ही अमूर्त कक्षाओं से वंचित होना चाहिए। यह इस नियम का उल्लंघन है जो उपरोक्त 'बराबर' विधि से 'super.equals' को कॉल नहीं करते हुए, अच्छी तरह से वर्णित समस्याओं का कारण बनता है। –

+0

@ पीटररोक मुझे यकीन नहीं है कि यह कैसे लागू होता है, क्योंकि एक अमूर्त वर्ग अभी भी 'बराबर' और 'हैशकोड' प्रदान कर सकता है। मेरे उदाहरण में, 'आकार' का बहाना सार है और इसमें दो उप-वर्ग हैं, 'रंगीन आकार' और 'रंगहीन आकार', जिनमें से केवल बाद में समानता के लिए रंग जांच जोड़ता है। एक ही समस्या है। – yshavit

+0

नहीं, क्योंकि यदि 'आकार' सार है, तो आपके पास 'आकार' ऑब्जेक्ट्स, केवल 'रंगीन आकार और/या' रंगहीन आकार 'नहीं हो सकती है। और इसके लिए आप 'super.equals' का उपयोग करके या बिना सही तरीके से 'बराबर' लागू कर सकते हैं। क्योंकि आपके पास ऐसी स्थिति कभी नहीं हो सकती है जहां ऑब्जेक्ट ओएफए * ए * बी है लेकिन ऑब्जेक्ट ओएफबी * ए * ए –