2012-04-26 15 views
11

मेरे पास निम्न सेटअप है जो मुझे एक संदेश दे रहा है जिसमें कहा गया है कि "कन्स्ट्रक्टर कॉल ओवरड्रिबल विधि"। मुझे पता है कि यह हो रहा है, लेकिन मेरा सवाल यह है कि इसे कैसे ठीक किया जाए ताकि कोड अभी भी काम करे और संदेश दूर हो जाए।"कन्स्ट्रक्टर कॉल ओवरराइड करने योग्य विधि" को ठीक करने के लिए कैसे करें

public interface Foo{ 
    void doFoo(); 
} 
public class FooImpl implements Foo{ 
@Override{ 
public void doFoo(){ 
    //.. Do important code 
} 
} 
public class Bar{ 
    private FooImpl fi; 
    public Bar(){ 
    fi = new FooImpl(); 
    fi.doFoo(); // The message complains about this line 
    } 
} 

धन्यवाद!

+0

जो कोड आपने दिखाया है वह ओवरराइड करने योग्य विधि * को * कन्स्ट्रक्टर कहलाता है, कन्स्ट्रक्टर * से नहीं, सही कह रहा है? या क्या मैं कुछ न कुछ भूल रहा हूं? – NPE

+0

कोड दिखा रहा है जो वास्तव में चेतावनी को रोकता है शायद एक अच्छा विचार होगा .. – Voo

+0

aix- यह संदेश उठा रहा है क्योंकि बार बार के कन्स्ट्रक्टर के अंदर fi.doFoo() को कॉल कर रहा है। वू - कोड कॉपी/पेस्ट करने के लिए बहुत लंबा तरीका है। यह – user973479

उत्तर

6

आप अंतिम रूप doFoo घोषित सकता है अगर आपको लगता है कि विधि बाद में ओवरराइड करने के लिए की जरूरत नहीं है:

public final void doFoo() { }

0

आपका आईडीई क्योंकि यह संभावित रूप से असुरक्षित है, कि तुम कह रहा है। आप किसी भी प्रत्यारोपण या डूफू प्रदान कर सकते हैं और सभी बार ऑब्जेक्ट्स स्टार्टअप पर अलग-अलग सामानों को बना सकते हैं। यह ज्यादातर मामलों में डिजाइन की खराब पसंद की तरह लगता है।

ऐसा लगता है कि आप एक कन्स्ट्रक्टर में एक रणनीति पैटर्न का उपयोग कर रहे हैं। कन्स्ट्रक्टर में रणनीति या किसी अन्य अतिदेय व्यवहार का उपयोग करना बुद्धिमान नहीं है। इसे किसी और जगह का प्रयोग करें।

+0

कन्स्ट्रक्टर में पूरी तरह से अलग वर्ग की एक गैर अंतिम विधि को कॉल करने के लिए संभावित रूप से असुरक्षित कैसे है? – Voo

+0

आपका उत्तर कम करने का कारण है क्योंकि आप किसी कन्स्ट्रक्टर में अतिसंवेदनशील व्यवहार के बाद के प्रभावों को समझ नहीं पाते हैं? यह लेख एक एक निर्माता में एक overridale विधि बुला का उपयोग करने का संभावित खतरा बताते हैं: http://www.javapractices.com/topic/TopicAction.do?Id=215 – Terraego

+1

आप वास्तव में अपनी पोस्ट पढ़ा था, तो आपने होगा ध्यान दिया गया है कि प्रश्न पहले से पूरी तरह से निर्मित ऑब्जेक्ट पर वर्चुअल विधि को कॉल करने के बारे में है। निर्मित वस्तु पर वर्चुअल विधियों को कॉल करने के जाने-माने गिरावट अच्छी तरह से जानी जाती हैं, लेकिन यहां आवेदन न करें। – Voo

0

आपके द्वारा देखी गई त्रुटि का स्रोत PMD ("ओवरर" के लिए वहां खोजें), और जब आपका उदाहरण दोबारा बनाते हैं, तो यह चेतावनी पीएमडी (4.2.6) के इस संस्करण द्वारा ट्रिगर नहीं की जाती है। सोनार सिर्फ पीएमडी, चेकस्टाइल और अन्य टूल्स को एकीकृत करता है, और एक सिंहावलोकन प्रदान करता है। तो जांचें कि आप किस सोनार (और पीएमडी) का उपयोग कर रहे हैं।

आप सोनार में देख सकते हैं: Sonar > Quality Profiles > Search for "overr" आपके द्वारा उपयोग किए जा रहे नियम को हाइलाइट करना चाहिए।

सोनार में, आप जांच सकते हैं कि आप किस पीएमडी का उपयोग कर रहे हैं। Sonar > Configuration > Update Center पर जाएं, और आप जिस पीएमडी का उपयोग कर रहे हैं उसके संस्करण पर देखें।

14

@Voo कहते हैं,

अपने प्रश्न पहले से ही एक पूरी तरह से निर्माण किया वस्तु पर एक आभासी विधि बुला के बारे में है। निर्माण वस्तु के लिए पर आभासी तरीकों को बुलाने की अच्छी तरह से ज्ञात पतन अच्छी तरह से जाना जाता है, लेकिन यहाँ

लागू नहीं है Effective Java 2nd Edition से, मद 17: डिजाइन और विरासत के लिए दस्तावेज़, वरना यह निषेध :

वहाँ कुछ और प्रतिबंध है कि एक वर्ग विरासत अनुमति देने के लिए का पालन करना चाहिए रहे हैं। रचनाकारों को सीधे या परोक्ष रूप से अतिरंजित विधियों, का आह्वान नहीं करना चाहिए। यदि आप इस नियम का उल्लंघन करते हैं, तो प्रोग्राम विफलता परिणाम होगा। सुपरक्लास कन्स्ट्रक्टर उपclass कन्स्ट्रक्टर से पहले चलता है, इसलिए उपclass कन्स्ट्रक्टर चलाने से पहले उपclass में ओवरराइडिंग विधि लागू की जाएगी। अगर ओवरराइडिंग विधि सबक्लास निर्माता, द्वारा किए गए किसी भी प्रारंभिकरण पर निर्भर करता है, तो विधि अपेक्षित व्यवहार नहीं करेगी।

ऑब्जेक्ट निर्माण के दौरान एक अतिरंजित विधि के आमंत्रण के परिणामस्वरूप अनियमित डेटा का उपयोग हो सकता है, जिससे रनटाइम अपवाद या अप्रत्याशित परिणामों तक पहुंच हो सकती है।

कंस्ट्रक्टर्स केवल तरीकों कि अंतिम या निजी

आप स्थिर कारखाने तरीकों का उपयोग कर सकता है समस्या आप Bar class से अपने वस्तुओं को बनाने के लिए है कि ठीक करने के लिए कर रहे हैं आह्वान करना होगा।

प्रभावी जावा, आइटम 1: विचार करें कंस्ट्रक्टर्स

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

public interface Foo { 
    void doFoo(); 
} 

और कार्यान्वयन:

public class FooImpl implements Foo { 
    @Override 
    public void doFoo() { 
    //.. Do important code 
    } 
} 

अपने कारखाने विधि के साथ अपने वर्ग बनाने के लिए आप इस तरह से काम कर सकता था:

तो, आप इंटरफेस के लिए जाना

  • चर के परिभाषित करने के लिए इंटरफ़ेस का उपयोग करें private FooImpl fi के बजाय आपकी कक्षा private Foo fi, कंक्रीट प्रकारों पर इंटरफेस का उपयोग करके अच्छा encapsulation और आपके कोड को ढीला करने के लिए कुंजी है।

  • अपने डिफ़ॉल्ट कन्स्ट्रक्टर को निजी बनाएं ताकि आपकी कक्षा के बाहर तत्कालता को रोक सके।

    निजी बार()

  • सभी तरीकों है कि अपने निर्माता में मौजूद हैं ओवरराइड करने के लिए कहता है निकालें { // इन्स्टेन्शियशन रोकता है}।

  • अपने स्थिर कारखाने पद्धति बनाएं

अंत में आप की तरह एक कारखाने विधि के साथ एक वर्ग Bar मिलती है:

public class Bar { 
    private Foo fi; 

    private Bar() {// Prevents instantiation 
     fi = new FooImpl(); 
    } 

    public static Bar createBar() { 
     Bar newBar = new Bar(); 
     newBar.fi.doFoo(); 

     return newBar; 
    } 
} 

मेरे बॉस कहते हैं: "सोनार चेतावनी के बारे में लक्षण कर रहे हैं, रोग के बारे में नहीं। जब आप बीमारी का इलाज कर सकते हैं तो यह सबसे अच्छा है। "

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