जावा डायनेमिक बाइंडिंग और ओवरराइडिंग विधि


89

कल मेरे पास दो घंटे का तकनीकी फोन साक्षात्कार था (जो मैंने पास किया, woohoo!), लेकिन मैंने जावा में डायनेमिक बाइंडिंग के संबंध में निम्नलिखित प्रश्न को पूरी तरह से टाल दिया। और यह दोगुना हैरान करने वाला है क्योंकि मैं इस कॉन्सेप्ट को अंडरग्रेजुएट्स को तब सिखाता था जब मैं कुछ साल पहले टीए था, इसलिए मैंने उन्हें गलत जानकारी देने की संभावना को थोड़ा परेशान किया है ...

यहाँ समस्या मुझे दी गई है:

/* What is the output of the following program? */

public class Test {

  public boolean equals( Test other ) {
    System.out.println( "Inside of Test.equals" );
    return false;
  }

  public static void main( String [] args ) {
    Object t1 = new Test();
    Object t2 = new Test();
    Test t3 = new Test();
    Object o1 = new Object();

    int count = 0;
    System.out.println( count++ );// prints 0
    t1.equals( t2 ) ;
    System.out.println( count++ );// prints 1
    t1.equals( t3 );
    System.out.println( count++ );// prints 2
    t3.equals( o1 );
    System.out.println( count++ );// prints 3
    t3.equals(t3);
    System.out.println( count++ );// prints 4
    t3.equals(t2);
  }
}

मैंने दावा किया है कि आउटपुट को ओवरराइड equals()विधि के भीतर से दो अलग-अलग प्रिंट स्टेटमेंट होने चाहिए : t1.equals(t3)और t3.equals(t3)। बाद का मामला काफी स्पष्ट है, और पूर्व मामले के साथ, भले हीt1 प्रकार ऑब्जेक्ट का संदर्भ हो, इसे टाइप टेस्ट के रूप में तुरंत दिया जाता है, इसलिए डायनेमिक बाइंडिंग को विधि के ओवरराइड किए गए फॉर्म को कॉल करना चाहिए।

जाहिरा तौर पर नहीं। मेरे साक्षात्कारकर्ता ने मुझे कार्यक्रम को चलाने के लिए प्रोत्साहित किया, और लो और निहारना, ओवरराइड विधि से केवल एक ही आउटपुट था: लाइन पर t3.equals(t3)

मेरा सवाल है, क्यों? जैसा कि मैंने पहले ही उल्लेख किया है, भले ही t1ऑब्जेक्ट ऑब्जेक्ट का संदर्भ है (इसलिए स्टैटिक बाइंडिंग ऑब्जेक्ट का equals()तरीका लागू करेगा ), डायनेमिक बाइंडिंग को संदर्भ के तात्कालिक प्रकार के आधार पर विधि के सबसे विशिष्ट संस्करण को लागू करने का ध्यान रखना चाहिए । मैं क्या खो रहा हूँ?


कृपया इस उत्तर के लिए मेरी पोस्ट खोजें जहां मैंने अतिरिक्त मामलों के साथ समझाने की पूरी कोशिश की है। मैं वास्तव में आपके इनपुट की सराहना करूंगा :)
देवेन्द्र लट्टू

जवाबों:


81

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

कुछ चर्चा यहाँ

तथ्य यह है कि यह समान पद्धति वास्तव में प्रासंगिक नहीं है, इसके अलावा यह ओवरराइड करने के बजाय अधिभार के लिए एक सामान्य गलती है, जिसे आप साक्षात्कार में समस्या के आपके उत्तर के आधार पर पहले से ही जानते हैं।

संपादित करें: एक अच्छा वर्णन यहाँ भी। यह उदाहरण पैरामीटर प्रकार से संबंधित एक समान समस्या दिखा रहा है, लेकिन उसी समस्या के कारण।

मेरा मानना ​​है कि यदि बाध्यकारी वास्तव में गतिशील थे, तो किसी भी मामले में जहां कॉलर और पैरामीटर टेस्ट का एक उदाहरण थे, जिसके परिणामस्वरूप ओवरराइड विधि को बुलाया जाएगा। इसलिए t3.equals (o1) एकमात्र ऐसा मामला होगा जो प्रिंट नहीं करेगा।


बहुत सारे लोग इंगित करते हैं कि यह अतिभारित है और अति-निषिद्ध नहीं है, लेकिन यहां तक ​​कि इसके साथ आप अपेक्षा करेंगे कि यह अतिभारित को सही ढंग से हल करेगा। आपकी पोस्ट वास्तव में केवल एक ही है जो इस प्रश्न का सही उत्तर देती है जहाँ तक मैं बता सकता हूँ।
बिल के

4
मेरी गलती इस तथ्य को पूरी तरह से याद कर रही थी कि विधि वास्तव में ओवरराइड की बजाय अतिभारित है। मैंने "बराबरी ()" देखी और तुरंत विरासत में मिली-और-ओवरराइड के बारे में सोचा। मुझे लगता है, अभी तक फिर से, व्यापक और अधिक कठिन अवधारणा को सही पाया, लेकिन सरल विवरण को खराब कर दिया। : पी
मैगसोल

14
एक अन्य कारण @Override एनोटेशन मौजूद है।
मैट

1
मेरे बाद दोहराएं: "जावा अतिभारित तरीकों के लिए स्थैतिक बंधन का उपयोग करता है, और
अतिप्रतिष्ठित

1
इसलिए मैंने यह नहीं जानते हुए स्नातक किया। धन्यवाद!
Atieh

25

की equalsविधि की विधि को Testओवरराइड नहीं करता equalsहै java.lang.Object। पैरामीटर प्रकार को देखो! Testवर्ग अधिक भार है equalsएक विधि है कि एक को स्वीकार करता है के साथ Test

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


हाँ, मुझे पूरा यकीन नहीं है कि मैंने उस सरल लेकिन महत्वपूर्ण विवरण को क्यों याद किया, लेकिन यह वही है जहाँ मेरी समस्या थी। धन्यवाद!
मागसोल

+1 प्रश्नकर्ता के जिज्ञासु परिणामों के सही उत्तर के लिए
मैट बी

कृपया इस उत्तर के लिए मेरी पोस्ट खोजें जहां मैंने अतिरिक्त मामलों के साथ समझाने की पूरी कोशिश की है। मैं वास्तव में आपके इनपुट की सराहना करूंगा :)
देवेन्द्र लट्टू

6

दिलचस्प रूप से पर्याप्त है, ग्रूवी कोड में (जिसे एक क्लास फ़ाइल में संकलित किया जा सकता है), सभी लेकिन कॉल में से एक प्रिंट स्टेटमेंट को निष्पादित करेगा। (किसी परीक्षण की किसी वस्तु से तुलना करने वाला व्यक्ति स्पष्ट रूप से Test.equals (टेस्ट) फ़ंक्शन को कॉल नहीं करेगा।) इसका कारण यह है कि groovy DOES पूरी तरह से गतिशील टाइपिंग नहीं करते हैं। यह विशेष रूप से रुचि है क्योंकि इसमें कोई भी चर नहीं है जो स्पष्ट रूप से गतिशील रूप से टाइप किया गया है। मैंने एक-दो स्थानों पर पढ़ा है कि यह हानिकारक माना जाता है, क्योंकि प्रोग्रामर उम्मीद करते हैं कि जावा चीज़ करने के लिए।


1
दुर्भाग्य से कीमत है कि Groovy के लिए भुगतान करता है एक बड़े पैमाने पर प्रदर्शन हिट है, क्योंकि हर विधि मंगलाचरण प्रतिबिंब का उपयोग करता है। एक भाषा को ठीक उसी तरह काम करने की अपेक्षा करना, जिस तरह एक दूसरे को आमतौर पर हानिकारक माना जाता है। मतभेदों से अवगत होने की जरूरत है।
जोआचिम सॉउर

JDK7 (या यहां तक ​​कि इसी तरह की कार्यान्वयन तकनीक का उपयोग करके) में इनविद्या के साथ अच्छा और तेज़ होना चाहिए।
टॉम हॉल्टिन -

5

जावा मापदंडों में सह-विचरण का समर्थन नहीं करता है, केवल रिटर्न प्रकारों में।

दूसरे शब्दों में, जबकि ओवरराइडिंग विधि में आपका रिटर्न प्रकार, ओवरराइड में जो था, उसका एक उपप्रकार हो सकता है, जो मापदंडों के लिए सही नहीं है।

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

नौकरी की साक्षात्कार प्रक्रिया के साथ गुड लक! मैं एक ऐसी कंपनी में साक्षात्कार करना पसंद करता हूँ जो इस प्रकार के प्रश्न पूछती है कि मैं अपने छात्रों को पढ़ाने वाले सामान्य प्रश्न / डेटा संरचनाओं के प्रश्नों के बजाय सामान्य प्रश्न पूछूं।


1
आपका मतलब है कंट्रोवर्सीट पैरामीटर।
टॉम हॉल्टिन -

मैंने किसी तरह इस तथ्य पर पूरी तरह से भरोसा किया कि विभिन्न विधि पैरामीटर आंतरिक रूप से एक अतिभारित विधि बनाते हैं, एक ओवरराइड नहीं। ओह चिंता मत करो, वहाँ भी / डेटा संरचनाओं सवाल अहं थे। : पी और शुभकामनाओं के लिए धन्यवाद, मुझे इसकी आवश्यकता होगी! :)
मैगसोल

4

मुझे लगता है कि इस तथ्य में निहित है कि बराबरी () विधि मानक के अनुरूप नहीं है: यह एक और टेस्ट ऑब्जेक्ट में है, ऑब्जेक्ट ऑब्जेक्ट नहीं है और इस तरह से बराबरी () विधि से आगे नहीं बढ़ रहा है। इसका मतलब है कि आपने वास्तव में केवल कुछ विशेष करने के लिए इसे ओवरलोड किया है जब इसे ऑब्जेक्ट ऑब्जेक्ट कॉल करते समय टेस्ट ऑब्जेक्ट दिया जाता है। किसी भी आईडीई के माध्यम से उस कोड को देखते हुए आपको टेस्ट के लिए दो बराबर () तरीके दिखाने चाहिए।


यह, और अधिकांश प्रतिक्रियाओं को बिंदु याद आ रहा है। मुद्दा इस तथ्य के बारे में नहीं है कि ओवरलोडिंग का उपयोग ओवरराइडिंग के बजाय किया जा रहा है। यही कारण है कि t1.equals (t3) के लिए ओवरलोड विधि का उपयोग नहीं किया जाता है, जब t1 को ऑब्जेक्ट के रूप में घोषित किया जाता है, लेकिन परीक्षण के लिए प्रारंभ किया जाता है।
रॉबिन

4

विधि को ओवरराइड करने के बजाय ओवरलोड किया जाता है। बराबर हमेशा एक ऑब्जेक्ट को पैरामीटर के रूप में लेते हैं।

btw, आपके पास इस पर एक आइटम है बलोच के प्रभावी जावा (जो आपको खुद चाहिए)।


जोशुआ बलोच का प्रभावी जावा?
डीजेकेवर्थ 19

प्रभावी हाँ, टाइप करते समय कुछ और सोच रहा था: D
गिल्स

4

कुछ समय के बाद डायनामिक बाइंडिंग (DD) और स्टेटिक बाइंडिंग (SB) में कुछ नोट :

1. समय पर अमल : (Ref.1)

  • DB: रन टाइम पर
  • एसबी: संकलक समय

2. के लिए इस्तेमाल किया :

  • DB: ओवरराइडिंग
  • SB: ओवरलोडिंग (स्थिर, निजी, अंतिम) (Ref.2)

संदर्भ:

  1. एक्सक्यूट का मतलब होता है रिसॉल्वर जिसका इस्तेमाल करना पसंद करते हैं
  2. क्योंकि संशोधक स्थैतिक, निजी या अंतिम के साथ विधि को ओवरराइड नहीं कर सकता है
  3. http://javarevisited.blogspot.com/2012/03/what-is-static-and-dynamic-binding-in.html

2

अगर एक और तरीका जोड़ा जाता है जो ओवरलोडिंग के बजाय ओवरराइड करता है तो यह रनिंग टाइम पर डायनेमिक बाइंडिंग कॉल को स्पष्ट करेगा।

/ * निम्नलिखित कार्यक्रम का आउटपुट क्या है? * /

public class DynamicBinding {
    public boolean equals(Test other) {
        System.out.println("Inside of Test.equals");
        return false;
    }

    @Override
    public boolean equals(Object other) {
        System.out.println("Inside @override: this is dynamic binding");
        return false;
    }

    public static void main(String[] args) {
        Object t1 = new Test();
        Object t2 = new Test();
        Test t3 = new Test();
        Object o1 = new Object();

        int count = 0;
        System.out.println(count++);// prints 0
        t1.equals(t2);
        System.out.println(count++);// prints 1
        t1.equals(t3);
        System.out.println(count++);// prints 2
        t3.equals(o1);
        System.out.println(count++);// prints 3
        t3.equals(t3);
        System.out.println(count++);// prints 4
        t3.equals(t2);
    }
}

1

मुझे गतिशील बनाम स्टेटिक बाइंडिंग के बारे में एक दिलचस्प लेख मिला। यह गतिशील बाध्यकारी का अनुकरण करने के लिए कोड का एक टुकड़ा है। इसने मेरे कोड को अधिक पठनीय बना दिया।

https://sites.google.com/site/jeffhartkopf/covariance


0

प्रश्न का उत्तर "क्यों?" यह है कि जावा भाषा कैसे परिभाषित की जाती है।

कोविरियन और कंट्रोवर्सी पर विकिपीडिया लेख उद्धृत करने के लिए :

रिटर्न प्रकार सहसंयोजक जावा प्रोग्रामिंग भाषा संस्करण J2SE 5.0 में लागू किया गया है। विधि के ओवरराइडिंग के लिए पैरामीटर प्रकार बिल्कुल समान (अपरिवर्तनीय) होना चाहिए, अन्यथा विधि एक समानांतर परिभाषा के साथ अतिभारित होती है।

अन्य भाषाएं अलग हैं।


मेरी समस्या लगभग 3 + 3 देखने और 9 लिखने के बराबर थी, फिर 1 + 1 और लिखना 2. मैं समझता हूं कि जावा भाषा कैसे परिभाषित की जाती है; इस मामले में, जो भी कारण के लिए, मैं पूरी तरह से कुछ ऐसा नहीं था, भले ही मैंने उस गलती से बचने के लिए एक ही समस्या में विधि को गलत तरीके से समझा।
मागसोल

0

यह बहुत स्पष्ट है, कि यहाँ कोई भी अवधारणा नहीं है। यह विधि अधिभार है। Object()ऑब्जेक्ट क्लास की विधि प्रकार ऑब्जेक्ट equal()के संदर्भ का पैरामीटर लेती है और यह विधि टाइप टेस्ट के संदर्भ का पैरामीटर लेती है।


-1

मैं इसे दो उदाहरणों के माध्यम से समझाने की कोशिश करूंगा जो कि कुछ उदाहरणों के विस्तारित संस्करण हैं जो मुझे ऑनलाइन आए थे।

public class Test {

    public boolean equals(Test other) {
        System.out.println("Inside of Test.equals");
        return false;
    }

    @Override
    public boolean equals(Object other) {
        System.out.println("Inside of Test.equals ot type Object");
        return false;
    }

    public static void main(String[] args) {
        Object t1 = new Test();
        Object t2 = new Test();
        Test t3 = new Test();
        Object o1 = new Object();

        int count = 0;
        System.out.println(count++); // prints 0
        o1.equals(t2);

        System.out.println("\n" + count++); // prints 1
        o1.equals(t3);

        System.out.println("\n" + count++);// prints 2
        t1.equals(t2);

        System.out.println("\n" + count++);// prints 3
        t1.equals(t3);

        System.out.println("\n" + count++);// prints 4
        t3.equals(o1);

        System.out.println("\n" + count++);// prints 5
        t3.equals(t3);

        System.out.println("\n" + count++);// prints 6
        t3.equals(t2);
    }
}

यहाँ, मान 0, 1, 2, और 3 के साथ लाइनों के लिए; हमारे पास संदर्भ के ऑब्जेक्ट के लिए O1 और t1 पर equals()विधि। इस प्रकार, संकलन समय पर, Object.class फ़ाइल equals()से विधि बाध्य हो जाएगी।

हालांकि, भले ही संदर्भ के t1 है वस्तु है, यह है intialization की टेस्ट वर्ग
Object t1 = new Test();
इसलिए, रन-टाइम पर यह कॉल करता है public boolean equals(Object other)जो कि ए

ओवरराइड विधि

यहां छवि विवरण दर्ज करें

अब, 4 और 6 के रूप में मानों के लिए, यह फिर से सीधा है t3 जिसमें संदर्भ और परीक्षण का प्रारंभ है , equals()वस्तु संदर्भ के रूप में पैरामीटर के साथ कॉलिंग विधि है और एक है

अतिभारित विधि

ठीक है!

फिर से, यह समझने के लिए कि संकलक किस विधि को कॉल करेगा, बस विधि पर क्लिक करें और ग्रहण समान प्रकार के तरीकों को उजागर करेगा जो यह सोचते हैं कि संकलन समय पर कॉल करेगा। यदि यह संकलन समय पर नहीं मिलता है, तो वे विधियाँ ओवरराइडिंग विधि का एक उदाहरण हैं।

यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.