java - software - जावा संप्रदाय




java verify (5)

public class CovariantTest {
    public A getObj() {
        return new A();
    }

    public static void main(String[] args) {
        CovariantTest c = new SubCovariantTest();
        System.out.println(c.getObj().x);
    }
}

class SubCovariantTest extends CovariantTest {
    public B getObj() {
        return new B();
    }
}

class A {
    int x = 5;
}

class B extends A {
    int x = 6;
}

संकलित और चलने पर उपरोक्त कोड 5 प्रिंट करता है। यह अति-ग्रस्त विधि के लिए लौकिक वापसी का उपयोग करता है

यह 6 के बजाय 5 प्रिंट क्यों करता है, क्योंकि यह कक्षा में ग़लत विधि प्राप्त ओओबीजे वर्ग subCovariantTest को कार्यान्वित करता है

क्या कोई इस पर कुछ प्रकाश डाल सकता है धन्यवाद।

https://code.i-harness.com


अपने ए और बी को ऊपर से बदलें:

class A {
    public int getX() { return 5; }
}

class B extends A {
    public int getX() { return 6; }
 }

वह शायद गलत प्रश्न के बारे में आपके प्रश्न का उत्तर देगा ;-)


ऑब्जेक्ट में एक्स नामित दो फ़ील्ड, कक्षा ए से एक और कक्षा बी से एक है, जो ए में एक को छुपाता है। सी का घोषित होने के कारण फ़ील्ड एक्स को ए में एक है।

व्यवहार में यह एक समस्या नहीं है, क्योंकि यह बहुत खराब शैली है

  • एक उप-कक्षा में फ़ील्ड छिपाएं,

  • एक विधि के माध्यम से सीधे एक फ़ील्ड का उपयोग करें


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

यहाँ क्या हो रहा है पर एक स्पष्टीकरण है। कार्यक्रम पहले कुछ ऐसी चीज़ों को प्राप्त करता है जो कि प्रकार A परोक्ष रूप से होता है और फिर x लिए कॉल करता है जिसे A से आना माना जाता है। हालांकि यह स्पष्ट रूप से एक उपप्रकार है, आपके उदाहरण में, B एक ऑब्जेक्ट SubCovariantTest के माध्यम से बनाया गया है, यह अभी भी मान लेता है कि आप getObj () में कुछ वापस लौटते हैं जो एब्जेक्टिक रूप से ए टाइप किया जाता है। चूंकि जावा फ़ील्ड को ओवरराइड नहीं कर सकता है, टेस्ट Ax को कॉल करेगा और नहीं Bx

CovariantTest c = new SubCovariantTest();
// c is assumed the type of CovariantTest as it is
// implicitly declared

System.out.println(c.getObj().x);
// In this method chain the following happens:

// c.getObj() will return object of type B
// BUT will assume it is an A

// c.getObj().x will return the x from A
// since in this context the compiler assumes 
// it is an A and make the call to A.x

ऐसा लगता है कि एक मनगटी हुई पकड़ क्योंकि विधि हमेशा जावा में ओवरराइड की जाती हैं (सी ++ और सी # की तुलना में वे नहीं हैं)। आप आमतौर पर इस समस्या में नहीं चलेगा क्योंकि जावा कोड कॉन्फ्रेंस आपको कभी भी फ़ील्ड को सीधे उपयोग नहीं करने के लिए कहता है। इसके बजाय सुनिश्चित करें कि फ़ील्ड्स हमेशा अभिगमर तरीकों के माध्यम से पहुंचाई जाती हैं , अर्थात गेटर्स :

class A {
    private int x = 5;

    public int getX() { // <-- This is a typical accessor method
        return x;
    }
}

class B extends A {
    private int x = 6;

    @override
    public int getX() {
        // will be called instead even though B is implied to be A
        // @override is optional because methods in Java are always virtual
        // thus are always overridden
        return x;
    }
}

यह कार्य करने के लिए कोड निम्नलिखित है:

c.getObj().getX();
// Will now call getX() in B and return the x that is defined in B's context.

समय को संकलित करने पर covariantTest के रूप में टाइप किया जाता है और इस प्रकार c.getObj () को कॉल करने के लिए समय को संकलित करने के लिए CovariantTest.getObj () विधि से जुड़ी होती है (और वह रनटाइम पर संशोधित नहीं किया जा सकता है)।

इसके अलावा, एक्स ए और बी दोनों में मौजूद है (यह छायांकित है, ओवरराइड नहीं है)। चूंकि कहा जा रहा है कि विधि CovariantTest.getObj () है और यह विधि ए के साथ काम करती है, एक्स पुनर्प्राप्त किया जा रहा है एक्स हालांकि वास्तविक वस्तु बी प्रकार की है।


ऐसा इसलिए है क्योंकि जावा सदस्य चर पर ओवरराइड नहीं होता है, वे छाया (विधियों के विपरीत)। दोनों ए और बी में वेरिएबल x है चूंकि सी कोवेरिएंट टेस्ट के रूप में घोषित किया गया है, getObj () की वापसी निहित रूप से ए है, बी नहीं है, इसलिए आपको ए का एक्स मिलता है, बी की एक्स नहीं।





java