2011-04-16 22 views
8

मैं इस काम की तरह कुछ कैसे कर सकते हैं:एक आंतरिक वर्ग से वंचित बाहरी वर्ग कैसे बनाया जाए?

class Outer { 
    int some_member; 

    abstract class InnerBase { 
    abstract void method(); 
    } 
} 

class OuterExtendsInner extends Outer.InnerBase { 
    OuterExtendsInner(Outer o) { o.super(); } 
    void method() { 
    // How do I use some_member here? 
    // Writing Outer.this.some_member -> error about Outer not being an enclosing class 
    // Writing just some_member -> no-go, either 
    } 
} 

वैकल्पिक हल InnerBase में एक विधि है कि Outer.this और व्युत्पन्न वर्ग से है कि कॉल देता है, लेकिन वहाँ एक और तरीका है?

मैं मुख्य रूप से बेहतर कोड-संगठन रखने के लिए इनरबेस को विस्तार से विस्तारित करना चाहता हूं, लेकिन मैं सभी व्युत्पन्न कक्षाओं को बाहरी में स्थानांतरित कर सकता हूं।

+3

"बेहतर कोड संगठन" में शायद ही कभी आंतरिक वर्ग शामिल होते हैं, और मैं कल्पना नहीं कर सकता कि इसमें कभी ऐसा कुछ शामिल है। – Anon

+0

यही कारण है कि मैं बाहरी वर्ग के बाहर भीतरी कक्षा का विस्तार करना चाहता था। मैं एक दुभाषिया को लागू कर रहा हूं, और प्रत्येक "आंतरिक" वर्ग एक प्रकार (नाम, पूर्णांक, आदि) मॉडल करता है। प्रकार के व्यवहार को बनाने वाले दुभाषिया ऑब्जेक्ट के संदर्भ की आवश्यकता हो सकती है या नहीं। मैं प्रत्येक विधि के लिए एक दुभाषिया संदर्भ पारित करके समस्या के आसपास चला गया है जिसकी आवश्यकता हो सकती है। – zvrba

उत्तर

3

समस्या यह है कि सिंथेटिक फ़ील्ड जो InnerBase से Outer लिंक करता है एक निजी क्षेत्र है। इस प्रकार, हम बाहरी ऑब्जेक्ट को केवल InnerBase के भीतर से एक्सेस कर सकते हैं, या यदि कुछ विधि या फ़ील्ड उसी ऑब्जेक्ट का संदर्भ प्रदान करता है।

+1

+1: इस विषमता को स्पष्ट करने में मदद के लिए धन्यवाद! –

3

आप OuterExtendsInner में ऐसा कर सकता है:

class OuterExtendsInner extends Outer.InnerBase { 
    Outer o; 

    OuterExtendsInner(Outer o) { 
     o.super(); 
     this.o = o; 
    } 

    void method() { 
     // now you can reference o.some_member 
     int x = o.some_member; 
    } 
} 
+0

यही वह प्रश्न है जो मैंने पहले से ही प्रश्न में सुझाया है (यद्यपि, इनरबेस में एक विधि से Outer.this के संदर्भ को वापस कर रहा है)। – zvrba

+0

ओह, मैंने जवाब को किसी अन्य तरीके से अपडेट किया है। – WhiteFang34

+0

इसके अलावा, बाहरी के दो उदाहरण होंगे। OuterExtendsInner में InnerBase। एक विरासत में मिला और एक निर्माता में प्राप्त किया। आप 'some_member' के बारे में बात नहीं करेंगे। – JVerstry

0

खैर आपकी समस्या InnerBase के प्रत्येक उदाहरण (मैं जानता हूँ कि यह सार है) एक Outer वस्तु के लिए एक संदर्भ के लिए किया है। यह नेस्टेड कक्षाओं के अर्थशास्त्र का हिस्सा है। OuterExtendsInner को तत्काल संदर्भ देने की आवश्यकता होगी। आप InnerBasestatic नेस्टेड क्लास बनाने से बच सकते हैं।

+0

यह समस्या नहीं है, समस्या यह है कि इस 'बाहरी' ऑब्जेक्ट का संदर्भ कैसे प्राप्त करें। –

1

उत्तर है: आप नहीं कर सकते, क्योंकि यह encapsulation तोड़ देगा। केवल इनरबेस के पास बाहरी के गुणों तक पहुंच हो सकती है, न कि OuterExtendsInner। यह प्रत्यक्ष विरासत नहीं है। इनरबेसबेस बाहरी का उत्तराधिकारी नहीं है।

+0

ठीक है, आप कर सकते हैं, क्योंकि बाहरी के गुण वास्तव में इनरबेस के गुण नहीं हैं, वे सिंटैक्टिक रूप से दिखते हैं जैसे कि वे हैं (कम से कम, इस तरह यह होता था - मैं कल्पना नहीं कर सकता कि यह बदल जाएगा)। इसके अलावा, इस समस्या में बाहरी के निजी गुणों की प्रत्यक्ष पहुंच शामिल नहीं है। –

+0

लेकिन OuterExtendsInner इनरबेस से विरासत में आता है, और इसलिए इसमें इनरबेस के पास पहुंचने वाली सभी चीज़ों तक पहुंच होनी चाहिए। – zvrba

+0

@ रॉबिन ग्रीन कृपया एक परिचालन उदाहरण प्रदान करें, लेकिन आप देखेंगे कि यह संभव नहीं है। OuterExtendsInner बाहरी के गुणों तक नहीं पहुंच सकता है। – JVerstry

1

मैंने व्हाइटफैंग 34 के उत्तर की कोशिश नहीं की है। यह काम कर सकता है, लेकिन मैं इस पर स्पष्ट नहीं हूं ...

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

class Outer { 
    int some_member; 

    abstract class InnerBase { 
    abstract void method(); 
    } 
} 

class OuterExtendsOuter extends Outer { 
    class InnerExtendsInner extends Outer.InnerBase { 
    void method() { 
     System.out.println(some_member); 
    } 
    } 
} 

मैं वास्तव में या तो इस कोड नहीं चला है, लेकिन यह काम करना चाहिए।

अद्यतन:

टिप्पणी थ्रेड के आधार पर, मैं अब संकलित और ऊपर मेरी कोड और WhiteFang34 के कोड दोनों समाप्त हो गया है।

वास्तव में दोनों काम करते हैं, लेकिन जैसा कि पालो एबरमान द्वारा टिप्पणियों में उल्लेख किया गया है, दोनों तत्काल आंतरिक कक्षा के अंदर बाहरी की दो प्रतियां बनाते हैं।

मैं पैलो के जवाब को ऊपर उठाने जा रहा हूं, और यह केवल रणनीति द्वारा ऐसा करने की कोशिश नहीं करने का समर्थन करेगा, क्योंकि यह वास्तव में आंतरिक वर्ग तंत्र का दुरुपयोग है।

बस अपनी विस्तारित आंतरिक कक्षाएं एक ही बाहरी कक्षा के अंदर रहें!

अद्यतन 2:

क्या मेरी कोड में होता है, एक डिबगर का उपयोग कर क्रम परीक्षा पर और वर्गों के javap निरीक्षण से उत्पादन की जांच के आधार पर, कि दोनों InnerBase और OuterExtendsOuter$InnerExtendsInner सिंथेटिक निजी अंतिम नामित क्षेत्रों है this$0। क्योंकि कोई कंस्ट्रक्टर्स स्पष्ट रूप से परिभाषित कर रहे हैं, डिफ़ॉल्ट कंस्ट्रक्टर्स उपयोग किया जाता है, और कोड स्निपेट

OuterExtendsOuter outer = new OuterExtendsOuter(); 
    Outer.InnerBase inner = outer.new InnerExtendsInner(); 

दोनों संदर्भ outer करने के लिए इन दो क्षेत्रों का कारण बनता है।

दूसरे शब्दों में, पालो की टिप्पणी पूरी तरह से सही है।

आगे प्रयोग करके, एक ही वास्तव में अगर आप Outer का एक और भीतरी कक्षा में InnerBase का विस्तार होता है, तो यह थोड़ा के साथ यह एक ही बाहरी कक्षा या इसके बारे में एक विस्तार में परिभाषित किया जा रहा करने के लिए है, लेकिन वास्तव में एक परिणाम है गैर स्थैतिक आंतरिक कक्षाओं को आम तौर पर कैसे संभाला जाता है।

मुझे संदेह है कि यह कहीं भी दस्तावेज है, लेकिन मैंने इसे नहीं देखा है।

शायद विरासत और आंतरिक कक्षाओं को जितना संभव हो सके मिश्रण करने के लिए सबसे अच्छा!

+0

यह 'InnerExtendsInner' ऑब्जेक्ट में कक्षाओं को संलग्न करने के लिए दो लिंक हैं (एक' इनरएक्सएक्सेंडइनर 'और' इनरबेसबेस 'के लिए एक), जो मौके से (जैसे डिफ़ॉल्ट कन्स्ट्रक्टर द्वारा) एक ही ऑब्जेक्ट को इंगित करता है। –

+0

@ पालो एबरमान: मैं आपका अनुसरण नहीं करता हूं। शायद मुझे वास्तव में संकलन और कोड चलाने की कोशिश करनी होगी ... –

+0

मुझे लगता है कि यह काम करेगा, लेकिन वास्तव में यह व्हाइटफैंग द्वारा स्पष्ट 'बाहरी' संदर्भ के उत्तर के समान है। (मुझे एक छवि करना चाहिए, लेकिन मेरे पास इस टिप्पणी में पर्याप्त जगह नहीं है।) –

1

बस इनरबेस में एक गेटर विधि है?

class Outer { 
    int some_member; 

    abstract class InnerBase { 
    abstract void method(); 
    protected int getSome_Member() // This is possible, because Abstract classes can have non-abstract methods. 
    { 
     return some_member; 
    } 
    } 
} 

class OuterExtendsInner extends Outer.InnerBase { 
    OuterExtendsInner(Outer o) { o.super(); } 
    void method() { 
     // you can access "some_member" now 
     int myNumber = getSome_Member(); 

    } 
} 
0

बाहरी वर्ग आंतरिक कक्षा को बढ़ा सकता है अगर आंतरिक वर्ग ".class" में संकलित किया गया हो।

अब, हर बार जब आप बाहरी वर्ग यह मुठभेड़ों संकलन जो

अभी तक संकलित नहीं है और संकलक एक NoClassDefException या ClassNotFoundException फेंक जाएगा "innerclass फैली"।

है ना? तो आप कभी भी उस आंतरिक वर्ग को संकलित नहीं करेंगे। यदि आप इस समस्या को

पर काबू पा सकते हैं तो आप भीतरी कक्षा का विस्तार कर सकते हैं :)।

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