2010-05-14 20 views
10

मेरे पास बेस क्लास में परिभाषित एक स्थिर विधि है, मैं इस विधि को अपने बच्चे वर्ग में ओवरराइड करना चाहता हूं, क्या यह संभव है?क्या व्युत्पन्न कक्षा में एक स्थिर विधि को ओवरराइड करना संभव है?

मैंने कोशिश की लेकिन यह मेरी अपेक्षा के अनुसार काम नहीं किया। जब मैंने कक्षा बी का एक उदाहरण बनाया और अपनी कॉल() विधि का आह्वान किया, कक्षा ए में स्थैतिक foo() विधि लागू की गई है।

public abstract class A { 
    public static void foo() { 
    System.out.println("I am base class"); 
    } 

    public void callMe() { 
    foo(); 
    } 
} 

Public class B { 
    public static void foo() { 
     System.out.println("I am child class"); 
    } 
} 
+2

आपको नहीं होना चाहिए किसी ऑब्जेक्ट से पहले स्थान पर स्थैतिक विधियों को कॉल करना, आपको इसे कक्षा से कॉल करना चाहिए। –

उत्तर

16

स्थिर विधि कॉल संकलन समय (कोई गतिशील प्रेषण) पर हल नहीं होते हैं।

class main { 
    public static void main(String args[]) { 
      A a = new B(); 
      B b = new B(); 
      a.foo(); 
      b.foo(); 
      a.callMe(); 
      b.callMe(); 
    } 
} 
abstract class A { 
    public static void foo() { 
     System.out.println("I am superclass"); 
    } 

    public void callMe() { 
     foo(); //no late binding here; always calls A.foo() 
    } 
} 

class B extends A { 
    public static void foo() { 
     System.out.println("I am subclass"); 
    } 
} 

I am superclass 
I am subclass 
I am superclass 
I am superclass 
+0

मैंने अपना दिमाग बदल दिया और "कोई गतिशील प्रेषण" लिखा, क्योंकि इसमें शामिल सामान्य अवधारणा है। – Artefacto

+0

उह, आप callMe() का उपयोग नहीं करते हैं ... – RCIX

+1

सही शब्द "सुपरक्लास" और "सबक्लास" हैं, न कि "बेस क्लास" और "बाल वर्ग"। – Jesper

0

नहीं। यह संभव नहीं है।

कुछ समान (समान नहीं) प्रश्न here और here

4

जावा में, स्थिर विधि लुकअप संकलन समय पर निर्धारित कर रहे हैं देता है और उपवर्गों जो संकलन के बाद लोड किए गए हैं के लिए अनुकूल नहीं कर सकते।

1

बस इसे क्यों जोड़ें। आम तौर पर जब आप किसी विधि को ऑब्जेक्ट करते हैं तो विधि का उपयोग उपयुक्त कार्यान्वयन को खोजने के लिए किया जाता है। आपको ऑब्जेक्ट को माता-पिता द्वारा प्रदान किए गए किसी का उपयोग करने के बजाय अपनी विधि प्रदान करके किसी विधि को ओवरराइड करने की क्षमता मिलती है।

स्थैतिक तरीकों के मामले में उपयोग करने के लिए कौन सा कार्यान्वयन आपको बताने के लिए उपयोग करने के लिए कोई वस्तु नहीं है। इसका मतलब है कि संकलक कॉल करने के तरीके के कार्यान्वयन को चुनने के लिए केवल घोषित प्रकार का उपयोग कर सकता है।

0

स्थिर तरीके संकलित समय पर हल किए जाते हैं। इसलिए यदि आप मूल श्रेणी विधि को कॉल करना चाहते हैं तो आपको स्पष्ट रूप से नीचे क्लासनाम या उदाहरण के साथ कॉल करना चाहिए।

A.foo(); 

या

A a = new A(); 
a.foo(); 
24

Can I override a static method?

बहुत से लोग सुना है कि आप एक स्थिर विधि ओवरराइड नहीं कर सकते। यह सच है - आप नहीं कर सकते। लेकिन यह इस तरह कोड लिखने के लिए संभव है:

class Foo { 
    public static void method() { 
     System.out.println("in Foo"); 
    } 
} 

class Bar extends Foo { 
    public static void method() { 
     System.out.println("in Bar"); 
    } 
} 

यह संकलित करता है तथा ठीक चलाता है। क्या यह एक स्थिर विधि का एक उदाहरण है जो एक और स्थैतिक विधि को ओवरराइड कर रहा है? जवाब नहीं है - यह एक स्थिर विधि को छुपा एक स्थिर विधि का एक उदाहरण है। यदि आप एक स्थिर विधि को ओवरराइड करने का प्रयास करते हैं, तो कंपाइलर वास्तव में आपको रोक नहीं देता है - यह ऐसा नहीं करता जो आपको लगता है कि यह करता है।

तो क्या अंतर है?

संक्षेप में, जब आप किसी विधि को ओवरराइड करते हैं, तब भी आपको रन-टाइम पॉलीमोर्फिज्म का लाभ मिलता है, और जब आप छिपाते हैं, तो आप नहीं करते हैं। तो उसका क्या मतलब हुआ?इस कोड पर एक नज़र डालें:

class Foo { 
    public static void classMethod() { 
     System.out.println("classMethod() in Foo"); 
    } 

    public void instanceMethod() { 
     System.out.println("instanceMethod() in Foo"); 
    } 
} 

class Bar extends Foo { 
    public static void classMethod() { 
     System.out.println("classMethod() in Bar"); 
    } 

    public void instanceMethod() { 
     System.out.println("instanceMethod() in Bar"); 
    } 
} 

class Test { 
    public static void main(String[] args) { 
     Foo f = new Bar(); 
     f.instanceMethod(); 
     f.classMethod(); 
    } 
} 

आप इस चलाते हैं, उत्पादन फू में

instanceMethod() बार
classMethod() में है

क्यों हम से instanceMethod मिलता है बार, लेकिन foo से classMethod()? क्या हम इन दोनों तक पहुंचने के लिए एक ही इंस्टेंस एफ का उपयोग नहीं कर रहे हैं? हां हम हैं - लेकिन चूंकि कोई ओवरराइड कर रहा है और दूसरा छुपा रहा है, हम अलग-अलग व्यवहार देखते हैं।

उदाहरण के बाद से विधि() है (ड्रम रोल कृपया ...) एक उदाहरण विधि है, जिसमें बार फू से विधि को ओवरराइड करता है, रन समय पर जेवीएम उदाहरण के वास्तविक वर्ग का उपयोग करता है यह निर्धारित करने के लिए कि कौन सी विधि चलाना है। हालांकि एफ को फू के रूप में घोषित किया गया था, लेकिन हमने बनाया वास्तविक उदाहरण एक नया बार() था। तो रनटाइम पर, JVM को पता चलता है कि f एक बार उदाहरण है, और इसलिए यह Foo में से एक के बजाय बार में instanceMethod() को कॉल करता है। इस तरह जावा सामान्य रूप से उदाहरण विधियों के लिए काम करता है।

कक्षा मोड() के साथ हालांकि। चूंकि (अहम) यह एक क्लास विधि है, संकलक और जेवीएम को विधि का आह्वान करने के लिए वास्तविक उदाहरण की आवश्यकता नहीं है। और यहां तक ​​कि यदि आप एक प्रदान करते हैं (जो हमने किया था: एफ द्वारा संदर्भित उदाहरण) जेवीएम इसे कभी नहीं देख पाएगा। कंपाइलर केवल संदर्भ के घोषित प्रकार को देखेगा, और उस घोषित प्रकार का उपयोग करेगा, संकलित समय पर, कॉल करने के लिए कौन सी विधि। चूंकि एफ को प्रकार फू के रूप में घोषित किया गया है, इसलिए संकलक f.classMethod() को देखता है और इसका निर्णय लेता है इसका मतलब है Foo.classMethod। इससे कोई फर्क नहीं पड़ता कि एफ द्वारा reffered उदाहरण वास्तव में एक बार है - स्थैतिक तरीकों के लिए, संकलक केवल संदर्भ के घोषित प्रकार का उपयोग करता है। जब हम कहते हैं कि एक स्थिर विधि में रन-टाइम पॉलीमोर्फिज्म नहीं है तो हमारा यही मतलब है।

क्योंकि उदाहरण विधियों और वर्ग विधियों में व्यवहार में यह महत्वपूर्ण अंतर है, उदाहरण के तरीकों के लिए हम अलग-अलग शर्तों का उपयोग करते हैं - "विधियों" के लिए "ओवरराइडिंग" और कक्षा के तरीकों के लिए "छिपाने" - दो मामलों के बीच अंतर करने के लिए। और जब हम कहते हैं कि आप एक स्थैतिक विधि को ओवरराइड नहीं कर सकते हैं, तो इसका अर्थ यह है कि यदि आप कोड लिखते हैं जो ऐसा लगता है कि यह एक स्थिर विधि ओवरराइड कर रहा है (जैसे इस पृष्ठ के शीर्ष पर पहले फू और बार) - यह नहीं होगा एक ओवरराइड विधि की तरह व्यवहार करते हैं। अधिक संदर्भ के लिए this

0

संक्षेप में स्थैतिक विधि ओवरराइडिंग पॉलिमॉर्फिज्म नहीं है, यह "विधि छिपाने" है। जब आप एक स्थिर विधि को ओवरराइड करते हैं तो आपको बेस क्लास विधि तक कोई पहुंच नहीं होगी क्योंकि यह व्युत्पन्न कक्षा से छिपा होगा .. सुपर() का उपयोग संकलन समय त्रुटि फेंक देगा ..

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