2011-01-29 13 views
29
public class A { 
    public void f1(String str) { 
     System.out.println("A.f1(String)"); 
     this.f1(1, str); 
    } 

    public void f1(int i, String str) { 
     System.out.println("A.f1(int, String)"); 
    } 
} 



public class B extends A { 
    @Override 
    public void f1(String str) { 
     System.out.println("B.f1(String)"); 
     super.f1(str); 
    } 

    @Override 
    public void f1(int i, String str) { 
     System.out.println("B.f1(int, String)"); 
     super.f1(i, str); 
    } 
} 


public class Main { 
    public static void main(String[] args) { 
     B b = new B(); 
     b.f1("Hello"); 
    } 
} 

मैं मांग कर रहा है कि इस कोड उत्पादन होगा:कॉलिंग आधार वर्ग अधिरोहित समारोह

B.f1(String) 
A.f1(String) 
A.f1(int, String) 

अभी तक मैं हो रही है:

B.f1(String) 
A.f1(String) 
B.f1(int, String) 
A.f1(int, String) 

मैं समझता हूँ कि नीचे एएफ 1 (स्ट्रिंग) में बी "यह" का संदर्भ बी का उदाहरण है। क्या मेरे पास चेन नई बी 1()। एफ 1 (स्ट्रिंग) -> (ए) एफ 1 (स्ट्रिंग) -> (ए) एफ 1 (इंट, स्ट्रिंग) करने का विकल्प है?

यह एक सैद्धांतिक सवाल है, व्यावहारिक रूप से समाधान स्पष्ट रूप से ए में एक निजी समारोह को लागू करने के लिए होगा जो एफ 1 (स्ट्रिंग) और एफ 1 (इंट, स्ट्रिंग) दोनों कॉल करेगा।

धन्यवाद,
मैक्सिम।

+2

मैंने प्रतिबिंब का उपयोग करने की कोशिश की (ए के f1 (int, स्ट्रिंग) के लिए विधि-वस्तु प्राप्त करना और इसे आमंत्रित करना), लेकिन यह काम नहीं किया। यह [ब्लॉग एंट्री] [1] सन के ब्लॉग्स में इंगित करता है कि जावा के साथ यह संभव नहीं है। [1]: http://blogs.sun.com/sundararajan/entry/calling_overriden_superclass_method_on – esaj

+0

@esaj लिंक –

उत्तर

29

दुर्भाग्य से, नहीं

के रूप में मुझे यकीन है कि जैसा कि आप जानते हैं, लेकिन मैं हूँ स्पष्ट रूप से पूर्णता के लिए राज्य - विधि आमंत्रण को नियंत्रित करने के लिए केवल 2 कीवर्ड हैं:

  • इस - - लागू उदाहरण के वर्ग (उदाहरण के "शीर्ष" आभासी मेज - परोक्ष डिफ़ॉल्ट) से शुरू विधि के लिए लग रहा है
  • सुपर - super.method() - वर्ग के माता पिता वर्ग से शुरू विधि के लिए लग रहा है, जिसमें लागू विधि परिभाषित किया गया है (प्रेरक वर्ग 'माता-पिता की आभासी सारणी - not strictly true, लेकिन इस तरह से सोचने के लिए सरल - धन्यवाद @maaartinus)

मैं किसी दूसरे कीवर्ड कल्पना कर सकते हैं (उदाहरण के लिए ? वर्तमान) तुम क्या वर्णन करते हैं:

  • वर्तमान - current.method() - वर्ग, जिसमें प्रेरक विधि

परिभाषित किया गया है, लेकिन जावा जैसे कोई कीवर्ड नहीं है से शुरू विधि के लिए लग रहा है (अभी तक?)।

+0

AFAIK, 'super.method()' माता-पिता के VT पर शुरू नहीं होता है। कोई वीटी लुकअप बिल्कुल नहीं है, यह निजी तरीकों को कॉल करने के समान तरीके से काम करता है। AFAIK, यह invokespecial का उपयोग कर संकलित हो जाता है। – maaartinus

+0

@मार्टिनस - धन्यवाद - आह, मुझे हर रोज कुछ नया सीखना अच्छा लगता है। इसलिए, 'invokevirtualstartingfromparent' निर्देश नहीं है - 'सुपर 'कॉल के लिए' invokespecial' का उपयोग किया जाता है और 'invokespecial' संकलन-समय बाध्यकारी का उपयोग करता है। इसलिए, 'सुपर' कॉल के समय, हम लक्ष्य विधि के संकलन-समय संकल्प को करने के प्रकार के बारे में पर्याप्त जानते हैं। यदि वह विधि ** ** ** प्रत्यक्ष सुपरक्लास में लागू नहीं है, तो मुझे लगता है कि पदानुक्रम की खोज के बराबर अभी भी आवश्यक है। क्या अंत परिणाम प्रभावी रूप से वही है? –

+0

मुझे नहीं लगता कि रनटाइम पर कोई भी लुकअप है, यहां तक ​​कि इस मामले में भी नहीं। IIUIC, 'सुपर' का अर्थ वास्तव में * पहले पूर्वज के पास है *। कंपाइलर को पूरे पदानुक्रम को जानना चाहिए, इसलिए यह वर्ग फ़ाइल में उचित पूर्वजों को लिखता है। यदि विधि वहां नहीं है (जिसे केवल किसी अन्य क्लासफ़ाइल का उपयोग करके चाल द्वारा किया जा सकता है), तो NoSuchMethodError फेंक दिया जाता है। – maaartinus

5

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

सी ++ में, इसके विपरीत, आपको समान व्यवहार प्राप्त करने के लिए स्पष्ट रूप से virtual फ़ंक्शन बनाना होगा।

16

मैं डर है, यह असंभव है, लेकिन वहाँ एक सरल समाधान का है:

public class A { 
    public void f1(String str) { 
     System.out.println("A.f1(String)"); 
     privateF1(1, str); 
    } 

    private void privateF1(int i, String str) { 
     System.out.println("A.f1(int, String)"); 
    } 

    public void f1(int i, String str) { 
     privateF1(i, str); 
    } 
} 
+2

एक विधि कॉल लगाकर this.' हमेशा निरर्थक है साथ 'पर अच्छा खोजने। –

-2
package main; 

public class A { 
public void f1(String str) { 
    System.out.println("A.f1(String)"); 
    if (this instanceof B) 
     new A().f1(1, str); 
    else 
     this.f1(1, str); 
} 

public void f1(int i, String str) { 
    System.out.println("A.f1(int, String)"); 
} 

} 

class B extends A { 
@Override 
public void f1(String str) { 
    System.out.println("B.f1(String)"); 
    super.f1(str); 
} 

@Override 
public void f1(int i, String str) { 
    System.out.println("B.f1(int, String)"); 
    super.f1(i, str); 
} 

public static void main(String[] args) { 
A a = new B(); 
    a.f1("Hello"); 
} 
} 
+0

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

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