2012-10-31 3 views
12

मेरे पास एक साधारण बेस क्लास है, जिसे बाद में कई अलग-अलग वर्गों द्वारा विस्तारित किया जाता है, जो संभावित रूप से नए फ़ील्ड पेश करते हैं, लेकिन जरूरी नहीं। मैंने आधार वर्ग में एक समान विधि को परिभाषित किया है, लेकिन कुछ उप-वर्गों के लिए भी इसे ओवरराइड किया है। क्या आधार/उप-वर्गों में परिभाषाओं को मिश्रण करना ठीक है? मेरे मामले में यह कोड फ़ील्ड को उसी फ़ील्ड की जांच से बचाना था।जावा - बेस क्लास में और उप-वर्गों में विधि बराबर है

+6

क्या आप परिभाषाओं को मिलाकर अपना मतलब बता सकते हैं। धन्यवाद। – tjg184

+0

बेस क्लास में एक परिभाषा होने के कारण, जो ओवरराइड हो सकता है/नहीं। मेरा कहना है कि "बेस क्लास परिभाषित बनाम सबक्लास परिभाषित करता है" – Bober02

उत्तर

22

एंजेलिका लैंगर से "Implementing equals() To Allow Mixed-Type Comparison" पर एक नज़र डालें।

के बराबर होती है अनुबंध का कहना है (अन्य लोगों के):

यह सममित है: के लिए किसी भी गैर-शून्य संदर्भ वेल्यू एक्स और वाई

यहाँ कुछ समस्याओं का एक संक्षिप्त विवरण और एक संभव समाधान है , x.equals (y) सत्य वापस आना चाहिए यदि केवल और y.equals (x) सत्य लौटाता है।

इसका मतलब है कि आप अगर अपने उप वर्ग नए क्षेत्रों पेश कर रहा है और आप इस उप वर्ग की एक वस्तु के आधार वर्ग की एक वस्तु (या किसी अन्य उप वर्ग कि बराबरी पर हावी नहीं होता) की तुलना कर रहे समस्याओं मिल सकता है ।

बदलें एक वर्ग तुलना के साथ instanceof की जाँच करें: क्योंकि आप

BaseClass baseClass = new BaseClass(); 
BadSubClass subClass = new BadSubClass(); 

System.out.println(baseClass.equals(subClass)); // prints 'true' 
System.out.println(subClass.equals(baseClass)); // prints 'false' 

सम्भावित समाधान मिल

class BaseClass { 
    private int field1 = 0; 

    @Override 
    public boolean equals(Object obj) { 
     if (obj instanceof BaseClass) { 
      return field1 == ((BaseClass) obj).field1; 
     } 
     return false; 
    } 
} 

class BadSubClass extends BaseClass { 
    private int field2 = 0; 

    @Override 
    public boolean equals(Object obj) { 
     if (obj instanceof BadSubClass) { 
      return super.equals(obj) 
        && field2 == ((BadSubClass) obj).field2; 
     } 
     return false; 
    } 
} 

:

निम्नलिखित नहीं करते

obj != null && obj.getClass() == getClass() 

इस समाधान के साथ BaseClass का कोई ऑब्जेक्ट किसी भी उप-वर्ग के किसी ऑब्जेक्ट के बराबर नहीं होगा।

आप equals विधि का एक @Override के बिना किसी अन्य SubClass बनाते हैं, तो दो SubClass -objects एक दूसरे को (यदि BaseClass.equals जांच का फैसला करता है तो) बॉक्स से बाहर है, लेकिन एक SubClass -object के बराबर होना कभी नहीं होगा के बराबर हो सकता है एक BaseClass -object।

class BaseClass { 
    private int field1 = 0; 

    @Override 
    public boolean equals(Object obj) { 
     if (obj != null && obj.getClass() == getClass()) { 
      return field1 == ((BaseClass) obj).field1; 
     } 
     return false; 
    } 
} 

class GoodSubClass extends BaseClass { 
    private int field2 = 0; 

    @Override 
    public boolean equals(Object obj) { 
     if (obj instanceof GoodSubClass) { 
      return super.equals(obj) && field2 == ((GoodSubClass) obj).field2; 
     } 
     return false; 
    } 
} 

कृपया लेख और अधिक उन्नत समस्याओं और उनके समाधान के लिए ऊपर उल्लेख का संदर्भ लें:

एक अच्छा कार्यान्वयन इस प्रकार हो सकता है।

+0

एंजेलिका लैंगर लेख लिंक के लिए धन्यवाद। हालांकि यह Liskov प्रतिस्थापन सिद्धांत, AFAIK का उल्लंघन करता है। जोशुआ ब्लॉक द्वारा फिर से "प्रभावी जावा" देखें। (हालांकि मैंने अभी तक पूरा लेख नहीं पढ़ा है।) – Puce

+1

o.getClass()! = This.getClass() के साथ क्या गलत है? – Mukul

+0

@ मुकुल मुझे लगता है कि यह वास्तव में बेहतर है क्योंकि यदि आप अतिरिक्त चेक नहीं करते हैं तो आप बराबर विधि को ओवरराइड करने की आवश्यकता से बचते हैं और आप सब कुछ तोड़ने के बिना 'super.equals()' को कॉल कर सकते हैं। मैंने बस एक संपादन के रूप में जमा किया – Qw3ry

0

मुझे लगता है कि जब तक आप eqauls() और hashcode() अनुबंधों का पालन करते हैं, तब तक यह बिल्कुल ठीक है।

0

आप वर्ग की विधि है कि आप कोड दोहराव

public class BaseClass { 
    public boolean equals(BaseClass other) { 
    return (other.getBlahblah() == this.Blahblah && .....); 
    } 
} 

public class DerivedClass extends BaseClass { 
    public boolean equals(DerivedClass other) { 
    return (super(other) && other.getNewAttribute() == this.NewAttribute.....); 
    } 
} 
+1

+1 सुपर सुपर को कॉल करने के लिए सलाह के लिए। एक नोट - यह वैध जावा कोड नहीं है, इसे ठीक करने के लिए यह अच्छा होगा (मुझे लगता है कि यह एक उदाहरण के रूप में सिर्फ एक छद्म कोड हो सकता है)। –

+0

धन्यवाद। मैंने बस अधिकांश चीजों पर चेक किए बिना इसे मिटा दिया। यह थोड़ी देर के बाद से मैं जावा कर रहा हूं और इसमें कुछ अन्य वाक्यविन्यास और इसके अंदर कॉल करना होगा। – Grambot

+0

आप ऑब्जेक्ट के बराबर ओवरराइड नहीं कर रहे हैं बल्कि ब्लोच के हमेशा संदर्भ के कारण इसे –

0

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

2

नहीं, बराबर विधि के लिए प्रासंगिक नए फ़ील्ड पेश करते समय बराबर अनुबंध के अनुरूप होना संभव नहीं है। अधिक जानकारी के लिए जोशुआ ब्लोच द्वारा "प्रभावी जावा" देखें।

संपादित करें:

मैं अभी हाथ में किताब नहीं है, लेकिन मैं instantiated नहीं किया जा सकता है लगता है कि यह ठीक है अगर आधार वर्ग सार है /।

+0

+1 ओवरलोड कर रहे हैं। और क्योंकि यह सच है – Jerome

+0

यह सार है :) – Bober02

0

मुझे लगता है, यही कारण है कि में Java किया superclass रूप equals(Object obj) और hashCode() विधि कार्यान्वयन प्रदान करने के लिए एकदम सही है। हम सभी जानते हैं कि जावा hashCode() and equals(Object obj) बेस क्लास java.lang.Object में विधि कार्यान्वयन प्रदान करता है, और जब भी हमें में हमारे class में आवश्यकता होती है।

0

जबकि निम्नलिखित प्रत्येक मामले को संभाल नहीं लेते हैं, मुझे यह काफी व्यावहारिक लगता है। मैंने कई बार इसका इस्तेमाल किया है जब मेरे पास सुपर क्लास और सबक्लस दोनों प्ले में हैं। मैं उन्हें तुलना करने की इच्छा नहीं करना चाहता, लेकिन मैं सब क्लास के लिए सुपरक्लास बराबर() को फिर से कार्यान्वित नहीं करना चाहता हूं। यह संभालता है:

  • a.equals (ख) == b.equals (क)
  • क्षेत्र तुलना कोड नकल नहीं करता
  • आसानी से किसी भी उपवर्ग गहराई के लिए सामान्यीकृत
  • Subclass.equals (सुपर क्लास) == झूठी
  • Superclass.equals (उपवर्ग) == झूठी

कोड उदाहरण

// implement both strict and asymmetric equality 
class SuperClass { 
    public int f1; 
    public boolean looseEquals(Object o) { 
     if (!(o instanceof SuperClass)) return false; 
     SuperClass other = (SuperClass)o; 
     return f1 == other.f1; 
    } 
    @Override public boolean equals(Object o) { 
     return looseEquals(o) && this.getClass() == o.getClass(); 
    } 
} 
class SubClass extends SuperClass { 
    public int f2; 
    @Override public boolean looseEquals(Object o) { 
     if (!super.looseEquals(o)) return false; 
     if (!(o instanceof SubClass)) return false; 
     SubClass other = (SubClass)o; 
     return f2 == other.f2; 
    } 
    // no need to override equals() 
} 
संबंधित मुद्दे