2013-03-10 5 views
11

मान लीजिए कि मेरे पास एक सार बेस क्लास है जो रननेबल इंटरफेस लागू करता है।क्या जावा में कन्स्ट्रक्टर से अमूर्त विधि को कॉल करना ठीक है?

public abstract class Base implements Runnable { 

    protected int param; 

    public Base(final int param) { 
     System.out.println("Base constructor"); 
     this.param = param; 
     // I'm using this param here 
     new Thread(this).start(); 
     System.out.println("Derivative thread created with param " + param); 
    } 

    @Override 
    abstract public void run(); 
} 

और यहां कुछ व्युत्पन्न वर्गों में से एक है।

public class Derivative extends Base { 

    public Derivative(final int param) { 
     super(param); 
    } 

    @Override 
    public void run() { 
     System.out.println("Derivative is running with param " + param); 
    } 

    public static void main(String[] args) { 
     Derivative thread = new Derivative(1); 
    } 

} 

मुद्दा यह है कि मैं अपने बेस वर्ग के बजाय यह हर बार कॉपी करने की कुछ सामान्य चीजें करते चाहते हैं। वास्तव में, यह ठीक चल रहा है, उत्पादन हमेशा एक ही है:

बेस निर्माता परम के साथ 1 व्युत्पन्न परम 1

साथ चल रहा है लेकिन यह जावा में सुरक्षित है बनाया व्युत्पन्न धागा एक धागा बुला शुरू करने के लिए कन्स्ट्रक्टर में अमूर्त विधि? क्योंकि, सी ++ और सी # में ज्यादातर मामलों में यह असुरक्षित है, जहां तक ​​मुझे पता है। धन्यवाद!

उत्तर

21

इस कोड को दर्शाता कर सकते हैं तुम क्यों कभी नहीं कॉल एक सार विधि, या किसी अन्य overridable विधि, एक निर्माता से कार्य करना चाहिए:

abstract class Super { 
    Super() { 
     doSubStuff(); 
    } 
    abstract void doSubStuff(); 
} 

class Sub extends Super { 
    String s = "Hello world"; 

    void doSubStuff() { 
     System.out.println(s); 
    } 
} 

public static void main(String[] args) { 
    new Sub(); 
} 

जब चलाने के लिए, यह प्रिंट null। इसका मतलब है कि एक निर्माता में केवल "सुरक्षित" विधियां निजी और/या अंतिम हैं।

दूसरी ओर, आपका कोड वास्तव में एक निर्माता से एक अमूर्त विधि नहीं कहता है। इसके बजाय, आप, प्रसंस्करण के लिए एक और धागा है, जो भी बदतर है करने के लिए एक गैर-आरंभिकृत वस्तु पारित के बाद से धागा आप शुरू कर रहे हैं प्राथमिकता दी जा सकती है और इससे पहले कि आपके Base इसके प्रारंभ खत्म निष्पादित।

+1

वहाँ एक निर्माता एक अमूर्त या आभासी विधि * जिसका अनुबंध निर्दिष्ट करता है कि यह एक निर्माता से कहा जा सकता है, इस तरह के एक संदर्भ से को कॉल करने के लिए सुरक्षित होना चाहिए फोन होने के बारे में कुछ भी अनुचित नहीं होगा, और केवल अन्य तरीकों से समान रूप से कर रहे हैं कह सकते हैं सुरक्षित *? – supercat

+1

@supercat: मुझे लगता है कि आप इस बात पर निर्भर करते हैं कि आप दस्तावेज़ीकरण पर कितना भरोसा करते हैं, आप इस तरह के दस्तावेज का पालन करने के लिए दूसरों पर भरोसा करते हैं, और आप इस तरह के वर्ग या किसी भी उप-वर्ग को उचित रूप से प्रसारित करने या याद रखने के लिए कभी भी कितना भरोसा करते हैं ऐसी चेतावनियों का संदर्भ लें। मेरी राय में, यह काफी विश्वास है। मैं उन चीज़ों को प्राथमिकता देता हूं जिन्हें स्वचालित परीक्षणों द्वारा सिद्ध किया जा सकता है, और ऐसा नहीं हो सकता है। –

+2

पर्याप्त मेला। मेरे मन में सबसे बड़ा उपयोग मामला एक ऐसी स्थिति के लिए था जहां एक व्युत्पन्न वर्ग को एक स्थिरता को वापस करने के लिए एक विधि को ओवरराइड करने की उम्मीद की जाएगी जो प्रत्येक उप-वर्ग के सभी उदाहरणों के लिए समान होनी चाहिए, और जिसे कन्स्ट्रक्टर और अन्य जगहों की आवश्यकता होगी, इसलिए एक सामान्य कार्यान्वयन 'int getWoozleForType() {वापसी 23;} 'होगा। कन्स्ट्रक्टर को ऐसी चीज पास करना और इसे एक उदाहरण क्षेत्र में स्टोर करना थोड़ा मुश्किल लगता है, और मैं किसी भी अन्य दृष्टिकोण के बारे में नहीं सोच सकता जो कि आमंत्रित करता है। – supercat

3

एक निर्माता से एक अमूर्त विधि को कॉल करने के लिए यह एक बहुत ही बुरा अभ्यास है। ओवरराइडिंग को रोकने के लिए रचनाकारों से बुलाए जाने वाले तरीके हमेशा निजी या अंतिम होना चाहिए।

एक सवाल here

2
नहीं

एक अच्छा विचार के बाद से जब चलाने() उत्पन्न होता है, व्युत्पन्न वस्तु प्रारंभ नहीं किया गया है यह लिंक देखें। यदि रन() व्युत्पन्न में किसी भी राज्य पर निर्भर करता है, तो यह असफल हो सकता है।

आपके साधारण मामले में यह काम करता है। लेकिन फिर subclass के लिए कोई बात नहीं है। आप बस

public Base(final int param, Runnable action) { 

    new Thread(action).start(); 
1

this निर्माता से बाहर पासिंग कहा जाता है "निर्माता से दे this भागने", और कुछ विशेष रूप से गंदा और अजीब कीड़े को जन्म दे सकता है, क्योंकि वस्तु एक असंगत स्थिति में हो सकता है।

यह विशेष रूप से मामला है जब this, एक और धागा में भेजा जाता है इस उदाहरण में है। एक थ्रेड के भीतर बयानों को पुन: व्यवस्थित करने के लिए JVMs के कारण, आप अपरिभाषित व्यवहार/स्थिति उत्पन्न कर सकते हैं।

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