2015-06-03 3 views
6
class A{ 
    private void sayA(){ 
    System.out.println("Private method of A"); 
    } 
    public static void main(String args[]){ 
     A instanceA=new B(); 
     instanceA.sayA(); 
    } 
} 

class B extends A{ 
} 

मैं इसे उम्मीद कर रहा था संकलन समय पर के रूप में एक रन समय अपवाद फेंक संकलक जांच करता है कि sayA()A की और रन-टाइम में एक संदर्भ पर कहा जा सकता है कि यह जांच करेंगे अगर sayA()B पर कहा जा सकता है ' ऑब्जेक्ट लेकिन इसके बजाय इसे की निजी विधि मुद्रित की गई "।सुपर क्लास का निजी तरीका कैसे हल किया जाता है?

+4

कक्षा 'बी' के तहत 'मुख्य' को ले जाएं और आपको संकलन त्रुटि मिलनी चाहिए। –

+3

इस प्रश्न को वोट क्यों दिया जा रहा है? मुझे नहीं लगता कि सवाल किसी भी अंतर्दृष्टिपूर्ण विचार को उकसाता है। – 0xbaadf00d

+0

क्या हमारे पास सामान्य नहीं है "मैं व्यवहार्यता को कैसे समझता हूं?" डुप्लिकेट के रूप में पहले से ही झंडा करने के लिए सवाल? यदि नहीं, तो शायद यह एक अच्छा सवाल है :) –

उत्तर

5

क्योंकि आप एक करने के लिए बी बताए रहे हैं, इसलिए जिसके परिणामस्वरूप उदाहरण ए

के तरीकों की पहुंच है आप, बाद में लाइन संकलन नहीं होगा (जो मेरा मानना ​​है कि B instanceA=new B() को बदलते हैं, तो यह है जिसकी आपको उम्मीद है ?)।

class A{ 
    private void sayA(){ 
    System.out.println("Private method of A"); 
    } 
    public static void main(String args[]){ 
     B instanceA=new B(); 
     instanceA.sayA(); # This line won't compile/run. 
    } 
} 

class B extends A{ 
} 
+0

को उत्तेजित करने का विचार किया गया ... '((ए) इंस्टेंस ए)। एसएएए()' –

+0

हाँ वास्तव में काम करेगा क्योंकि आप ' ए – blazetopher

+1

पर कास्टिंग कर रहा है क्या यह वास्तव में जावा में सच है? यह बहुत असंगत लगता है। सी # इस प्रकार की अनुमति देता है, भले ही वेरिएबल के प्रकार (जब तक यह 'ए' से प्राप्त होता है) - लेकिन आप कहीं भी 'ए' से 'बी' के निजी लोगों को स्पर्श नहीं कर सकते हैं। – Luaan

12

private का अर्थ है कि केवल वह वर्ग जो फ़ील्ड घोषित करता है उसे देख सकता है। क्योंकि आप को A के भीतर से कॉल कर रहे हैं, विधि दिखाई दे रही है और कोड दोनों संकलित और चलाता है। यदि आप उस विधि को B या किसी अन्य वर्ग के भीतर से कॉल करने का प्रयास करना चाहते हैं तो आपको संकलन चेतावनी मिलेगी कि The method sayA() from the type A is not visible

+0

रनटाइम पर, 'instanceA'' बी 'की ऑब्जेक्ट का जिक्र कर रहा है, फिर' instanceA.sayA(); 'कैसे हल हो जाता है? संकलन-समय मैं सहमत हूं और समझता हूं जैसा आपने समझाया है – spiderman

+7

'बी ए बढ़ाता है', इसलिए 'बी' का कोई भी उदाहरण * ए 'का एक उदाहरण भी है। इसलिए 'ए' द्वारा घोषित निजी विधि 'instanceA' में मौजूद है लेकिन केवल वर्ग' ए 'में इसकी दृश्यता है। – 1337joe

+0

सही .. इसे मिला .. मैंने अपने बालों को खींचना बंद कर दिया। – spiderman

14

अभिगम्यता एक संकलित समय अवधारणा है (प्रतिबिंब एपीआई में प्रतिबिंबित)।

From the Java Language Specification

नोट है कि पहुँच एक स्थिर संपत्ति है कि संकलन समय पर निर्धारित किया जा सकता है; यह केवल प्रकार और घोषणा modifiers पर निर्भर करता है।

है, संकलक परवाह नहीं करता क्या उदाहरण instanceA नामित अपने चर द्वारा संदर्भित क्रम प्रकार

A instanceA = new B(); 

यह केवल परवाह करता है आप स्थिर के संदर्भ पर एक विधि लागू है कि हो जाएगा A टाइप करें। यह विधि private है और चूंकि आप उस वर्ग के शरीर के भीतर हैं जो इसे घोषित करता है, यह दृश्यमान है, और इसलिए उपयोग योग्य है।

अन्यथा, सदस्य या निर्माता निजी घोषित किया जाता है, और उपयोग अगर और अनुमति दी है, बशर्ते यह वही शीर्ष स्तर वर्ग (§7.6) के शरीर कि किसी सदस्य या निर्माता की घोषणा encloses के भीतर होती है ।


टिप्पणी में स्पाइडरमैन, पर विचार निम्नलिखित

class A { 
    private void privateMethod() { 
     System.out.println("private method"); 
    } 
    public void publicMethod() { 
     privateMethod(); 
    } 
} 

class B extends A {} 

class Example { 
    public static void main(String[] args) { 
     new B().publicMethod(); 
    } 
} 
+0

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

+1

@spiderman अभिगम्यता रनटाइम की संपत्ति नहीं है। यह संकलन समय की एक संपत्ति है। जेएलएस के नियम संकलन समय पर लागू होते हैं। वे सबकुछ पकड़ने के लिए हैं (वैध कंपाइलर के साथ)। रनटाइम पर इन नियमों को तोड़ने की कोई संभावना नहीं होगी (प्रतिबिंब के मामले को छोड़कर जहां इसे अलग-अलग संभाला जाता है)। –

+1

ठीक है, धन्यवाद +1। मुझे खुद को इस बात से सहमत होने के लिए मजबूर होना पड़ता है कि नियमों के अनुसार यह 'यह कैसे काम करता है' है। हालांकि, ओपी द्वारा इस उदाहरण में, क्या यह प्रदर्शित नहीं करता है कि रनटाइम पर बकाया टूट रहे हैं? और यह इसे पकड़ने में सक्षम नहीं है क्योंकि अभिगम्यता केवल संकलन-समय की संपत्ति है? .. कृपया मुझे पता है कि क्या आप मेरा प्रश्न प्राप्त कर रहे हैं। अपने समय की सराहना करें – spiderman

1

InstanceA, एक वास्तव में का उदाहरण है, तो यह एक के कार्यों कॉल कर सकते हैं, लेकिन अगर समारोह निजी है, इसका मतलब है कि के लिए केवल वर्ग घोषित करता है कि क्षेत्र इसे देख सकता है। जैसे:

public class A 
{ 
    private void sayA(){ 
     System.out.println("Private method of A"); 
    } 

    public void funOfA(){ 
     System.out.println("fun of A"); 
    } 
    public static void main(String args[]){ 
     A instanceA=new B(); 
     instanceA.sayA(); 
     instanceA.funOfA(); 
    } 

} 



public class B extends A 
{ 
    public void funOfB() 
    { 
     System.out.println("fun of B"); 
    } 
    public static void main(String args[]){ 
     A instanceA=new B(); 
     instanceA.funOfA(); 
    // instanceA.sayA(); // This Line won't compile and run. 
    // instanceA.funOfB(); // This Line won't compile and run. 
     B instanceB = new B(); 
     instanceB.funOfA(); 
     instanceB.funOfB(); 
    // instanceB.sayA(); // This Line won't compile and run. 
    } 
} 
0

केवल आभासी तरीकों वास्तव में वर्ग उदाहरण के हिस्से हैं - आप this कहा जाता है बस एक स्थिर विधि है कि एक तर्क ले जा रहा है के रूप में सभी अन्य तरीकों कल्पना कर सकते हैं।

तो जब आप इस अधिक स्पष्ट रूप से दिखाने के लिए कोड को फिर से लिखने (ध्यान दें कि मैं सी # का उपयोग कर रहा है, जावा थोड़ा अलग है, लेकिन इसी सिद्धांत ज्यादातर लागू होता है):

class A 
{ 
    private static void sayA(A @this) 
    { 
    "Hi from A".Dump(); 
    } 

    public static void Test() 
    { 
    sayA(new B()); 
    } 
} 

class B : A { } 

यह यह बहुत आसान हो गया है अधिक स्पष्ट है कि विधि का दायरा क्या है - यह वास्तव में प्रकार के उदाहरण में केवल टाई प्रकार के लिए टाई नहीं है। कोई फर्क नहीं पड़ता कि आप new B().sayA() या new A().sayA() पर कॉल करते हैं, वही विधि कहा जाता है, बस एक अलग तर्क के साथ।

दूसरी ओर, आप B के अंदर से कोड लिख रहे हैं, sayA विधि बस से सुलभ नहीं है - फिर से, A.sayA(...), स्पष्ट रूप से दुर्गम है, क्योंकि यह A को निजी है।

जब आप विधि को सार्वजनिक या संरक्षित करते हैं, और वर्चुअल (जावा में डिफ़ॉल्ट) करते हैं तो यह बदलता है। उस स्थिति में, जिसे वास्तविक विधि कहा जाता है उस रनटाइम प्रकार पर निर्भर करता है जिसे आप विधि को कॉल कर रहे हैं, संकलन-समय प्रकार नहीं, न ही उस स्कोप जिसे आप इसे कॉल करते हैं। इसका मतलब है कि new B().VirtualA() संकलन-समय प्रकार अलग होने के बावजूद उसी विधि को ((A)new B()).VirtualA() के रूप में कॉल करेगा। और निश्चित रूप से new A().VirtualA()BVirtualA ओवरराइड के आधार पर (या नहीं हो सकता है) एक अलग विधि हो सकता है।

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