2011-04-12 13 views
14

इन कक्षाओं में int a चर पर विचार किया है:क्या होता है जब आधार और व्युत्पन्न वर्ग प्रत्येक में एक ही नाम के साथ चर

class Foo { 
    public int a = 3; 
    public void addFive() { a += 5; System.out.print("f "); } 
} 
class Bar extends Foo { 
    public int a = 8; 
    public void addFive() { this.a += 5; System.out.print("b "); } 
} 
public class test { 
    public static void main(String [] args){ 
     Foo f = new Bar(); 
     f.addFive(); 
     System.out.println(f.a); 
    } 
} 

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

लेकिन सार्वजनिक उदाहरण परिवर्तनीय a के बारे में क्या? क्या होता है जब दोनों बेस क्लास और व्युत्पन्न कक्षा में एक ही चर होता है?

उपरोक्त कार्यक्रम के उत्पादन

b 3 

यह कैसे होता है है?

+0

मैंने कोड में कुछ बदलाव किए हैं और यह नहीं समझ सकते कि क्या हो रहा है। मैंने बार में एक डिस्प्ले विधि जोड़ा और इसे मुख्य में बुलाया, लेकिन संकलक त्रुटि मिली। फू में एक डिस्प्ले विधि भी जोड़ा गया लेकिन आश्चर्यजनक रूप से बार के प्रदर्शन को निष्पादित किया गया। क्या यह जावा में एक दोष है? –

+0

@ सुजानबाई वह बहुरूपता है। संकलन समय: प्रारंभिक बाध्यकारी: संदर्भ प्रकार पर जांच होती है। रन टाइम: देर से बाध्यकारी: वास्तविक वस्तु के प्रकार पर कॉल किया जाता है। –

उत्तर

18

वास्तव में दो अलग-अलग सार्वजनिक उदाहरण चर हैं जिन्हें a कहा जाता है।

  • एक Foo ऑब्जेक्ट में Foo.a चर है।
  • एक बार ऑब्जेक्ट में Foo.a और Bar.a चर दोनों हैं।

जब आप चलाने के इस:

Foo f = new Bar(); 
    f.addFive(); 
    System.out.println(f.a); 

addFive विधि Bar.a चर अपडेट कर रहा है, और फिर Foo.a चर पढ़ने। Bar.a चर पढ़ने के लिए, यदि आप ऐसा करने की आवश्यकता होगी: है

System.out.println(((Bar) f).a); 

यहाँ क्या हो रहा है के लिए तकनीकी शब्द "छिपा"। एक उदाहरण के लिए जेएलएस section 8.3, और section 8.3.3.2 देखें।

ध्यान दें कि छुपा भी उसी हस्ताक्षर के साथ static विधियों पर लागू होता है।

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


सुझाया गया तरीका की (आकस्मिक) छुपा भ्रम से बचने के रूप में अपने private उदाहरण चर घोषित करने और मनुष्य और सेटर तरीके से उन तक पहुँच रहा है। गेटर्स और सेटर्स का उपयोग करने के लिए अन्य बहुत अच्छे कारण हैं।

+0

+1 यह सही है, लेकिन मुझे अभी भी समझ में नहीं आता क्यों –

+0

धन्यवाद। क्या केवल एफ का उपयोग कर बेस क्लास के एडफिव को कॉल करने का कोई तरीका है? – moonsun

+0

वाह! मैं चौंक गया। मुझे विश्वास करने के लिए इसे चलाने के लिए था। कृपया मुझे बताएं कि हम बार के चर को बाहर से कैसे एक्सेस कर सकते हैं? – euphoria83

4

JLS से

8.3.3.2 उदाहरण: उदाहरण चर के छिपने यह उदाहरण है कि पिछले अनुभाग में, लेकिन स्थिर चर उदाहरण चर के बजाय का उपयोग करता है के समान है।कोड: क्योंकि वर्ग में एक्स की घोषणा टेस्ट वर्ग प्वाइंट में एक्स की परिभाषा छुपाता

4.7 2 
4.7 2 

, इसलिए वर्ग टेस्ट नहीं वारिस क्षेत्र एक्स:

class Point { 
    int x = 2; 
} 
class Test extends Point { 
    double x = 4.7; 
    void printBoth() { 
     System.out.println(x + " " + super.x); 
    } 
    public static void main(String[] args) { 
     Test sample = new Test(); 
     sample.printBoth(); 
     System.out.println(sample.x + " " + 
               ((Point)sample).x); 
    } 
} 

उत्पादन का उत्पादन इसके सुपरक्लास पॉइंट से। यह ध्यान दिया जाना चाहिए, हालांकि, जबकि क्षेत्र वर्ग बिंदु वर्ग परीक्षण द्वारा विरासत में नहीं मिला है, फिर भी यह कक्षा परीक्षण के उदाहरणों द्वारा लागू किया गया है। अन्य शब्दों में, कक्षा परीक्षण के प्रत्येक उदाहरण में दो फ़ील्ड हैं, एक प्रकार int और एक प्रकार का डबल। दोनों फ़ील्ड नाम x को सहन करते हैं, लेकिन कक्षा परीक्षण की घोषणा के भीतर, सरल नाम x हमेशा वर्ग परीक्षण के भीतर घोषित फ़ील्ड को संदर्भित करता है। में कोड क्लास टेस्ट के उदाहरण विधियां क्लास प्वाइंट super.x के आवृत्ति चर x का संदर्भ ले सकती हैं।

कोड फ़ील्ड एक्स पहुँचने के लिए एक क्षेत्र का उपयोग अभिव्यक्ति का उपयोग करता है होगा पहुँच क्षेत्र वर्ग संदर्भ अभिव्यक्ति के प्रकार के द्वारा संकेत में एक्स नाम दिया है। इस प्रकार, अभिव्यक्ति sample.x एक डबल मूल्य, उदाहरण चर वर्ग टेस्ट में घोषित एक्सेस करता है, क्योंकि चर नमूना के प्रकार के टेस्ट है, लेकिन अभिव्यक्ति ((प्वाइंट) नमूना) .x किसी पूर्णांक तक पहुँचता है मान, उदाहरण चर वैरिएबल प्वाइंट में घोषित किया गया है, प्रकार बिंदु पर कास्ट की वजह से।

2

विरासत में, बेस क्लास ऑब्जेक्ट व्युत्पन्न वर्ग के उदाहरण को संदर्भित कर सकता है।

तो इस प्रकार Foo f = new Bar(); ठीक काम करता है।

अब जब f.addFive(); कथन का आह्वान किया जाता है तो यह वास्तव में बेस क्लास के संदर्भ चर का उपयोग करके व्युत्पन्न वर्ग उदाहरण की 'addFive() विधि को कॉल करता है। तो आखिरकार 'बार' वर्ग की विधि लागू हो जाती है। लेकिन जैसा कि आप 'बार' वर्ग की addFive() विधि देखते हैं, केवल 'बी' प्रिंट करता है और 'ए' का मान नहीं।

अगला कथन i.e. System.out.println(f.a) वह है जो वास्तव में उस मूल्य के प्रिंट को प्रिंट करता है जो अंततः पिछले आउटपुट में संलग्न हो जाता है और इसलिए आप अंतिम आउटपुट को 'बी 3' के रूप में देखते हैं। यहां उपयोग किए जाने का मूल्य 'फू' वर्ग का है।

आशा है कि यह चाल निष्पादन & कोडिंग स्पष्ट है और आप समझ गए कि आपने आउटपुट को 'बी 3' के रूप में कैसे प्राप्त किया।

+1

+1 वाह, यह भ्रमित है। खुशी है कि मैंने पायथन पर स्विच किया: ^) –

+1

@jcomeau_ictx - लेकिन मुझे लगता है कि आप अभी भी "जावा" टैग स्पेस में ट्रोल करना पसंद करते हैं ... :-) –

+0

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

-1

यहां एफ प्रकार का प्रकार है और एफ वैरिएबल बार ऑब्जेक्ट धारण कर रहा है लेकिन जावा रनटाइम कक्षा Foo से f.a प्राप्त करता है। ऐसा इसलिए है क्योंकि जावा परिवर्तनीय नाम संदर्भ प्रकार का उपयोग करके हल किए जाते हैं, न कि ऑब्जेक्ट जो इसका जिक्र कर रहा है।

+0

यह स्पष्टीकरण गलत है। असल में, यह वास्तव में 'f' का संकलन समय प्रकार है जो निर्धारित करता है कि' ए 'चर जो' f.a' को संदर्भित करता है। –

+0

संकलन-समय और रनटाइम प्रकार यहां समान नहीं है, फू? – euphoria83

+0

नहीं। 'F' का संकलन समय प्रकार' F' 'है, लेकिन 'f' द्वारा संदर्भित वास्तविक वस्तु का रनटाइम प्रकार' बार' है। स्पष्टीकरण यह कह रहा है कि निर्णय रनटाइम पर किया जाता है, जो भ्रामक है ... यदि वास्तव में गलत नहीं है। –

संबंधित मुद्दे