2011-04-23 10 views
13

जैसे कन्स्ट्रक्टर में इनिट विधि को कॉल करने के लिए स्वच्छ कोड का उल्लंघन है, नीचे दिए गए कोड में मेरी चिंता यह है कि कन्स्ट्रक्टर का परम वास्तव में कक्षा के उदाहरण फ़ील्ड में सीधे मैप नहीं किया जाता है। उदाहरण फ़ील्ड पैरामीटर से मूल्य प्राप्त करते हैं और जिसके लिए मैं initalize विधि का उपयोग कर रहा हूं। इसके अलावा, मैं कुछ सामान करता हूं ताकि बनाई गई ऑब्जेक्ट को सीधे उस कोड में उपयोग किया जा सके जो उदा। कॉलिंग ड्रॉबाउंडरीज()। मुझे लगता है कि यह एक अमूर्त अर्थ में कैनवास बनाने (प्रारंभ करने) के माध्यम से क्या कर रहा है।क्या यह

क्या मेरा कन्स्ट्रक्टर बहुत अधिक कर रहा है? अगर मैं बाहर से बाहर कन्स्ट्रक्टर में सामान को कॉल करने के तरीकों को जोड़ता हूं, तो यह गलत होगा। कृपया मुझे अपने विचार बताएं।

public class Canvas { 

private int numberOfRows; 
private int numberOfColumns; 
private final List<Cell> listOfCells = new LinkedList<Cell>(); 

public Canvas(ParsedCells seedPatternCells) { 
    initalizeCanvas(seedPatternCells); 
} 

private void initalizeCanvas(ParsedCells seedPatternCells) { 
    setNumberOfRowsAndColumnsBasedOnSeedPatten(seedPatternCells); 
    drawBoundaries(); 
    placeSeedPatternCellsOnCanvas(seedPatternCells); 
} 
... 

पीएस .: क्षमा करें अगर यह मूर्खतापूर्ण प्रश्न की तरह दिखता है; मेरे कोड एक OOP गुरु द्वारा समीक्षा की जा रही है और मैं सिर्फ चिंतित हूँ: -0

संपादित करें:

मैं) initalizeCanvas (में तरीकों के बारे में कुछ चिंता पढ़ा जा रहा से अधिक ग्रस्त - सौभाग्य से इन तरीकों हैं निजी और कोई अन्य तरीकों को कॉल न करें।

वैसे भी, नेट पर आगे के शोध के बाद मैंने इसे और अधिक पसंद करना शुरू कर दिया है ... मुझे आशा है कि आप लोग सहमत होंगे !!??

public class Canvas { 

private int numberOfRows; 
private int numberOfColumns; 
private final List<Cell> listOfCells = new LinkedList<Cell>(); 

private Canvas() { 
} 

public static Canvas newInstance(ParsedCells seedPatternCells) { 
    Canvas canvas = new Canvas(); 
    canvas.setNumberOfRowsAndColumnsBasedOnSeedPatten(seedPatternCells); 
    canvas.drawBoundaries(); 
    canvas.placeSeedPatternCellsOnCanvas(seedPatternCells); 
    return canvas; 
} 
+1

मुझे आपके कोड के साथ तर्कसंगत रूप से कुछ भी गलत नहीं दिख रहा है। इस मामले में –

उत्तर

11

आमतौर पर गैर-तुच्छ कोड रखने के लिए एक निर्माता के लिए यह एक बुरा विचार है। एक नियम के रूप में, रचनाकारों को खेतों में अधिकतर आपूर्ति मूल्यों को असाइन करना चाहिए। यदि किसी ऑब्जेक्ट को जटिल प्रारंभिक आवश्यकता होती है, तो प्रारंभिकता किसी अन्य वर्ग की जिम्मेदारी होनी चाहिए (आमतौर पर factory)। इस विषय पर मिस्को हेवरी के महान लेखन को देखें: Flaw: Constructor does Real Work

1

हालांकि यह करने का सबसे शानदार तरीका नहीं है, मैं इसे ओओ परिप्रेक्ष्य से त्रुटिपूर्ण नहीं देखता हूं। हालांकि, यदि आप कक्षा के भीतर कहीं और से private विधि initalizeCanvas पर कॉल नहीं कर रहे हैं, तो आप उन तीन पंक्तियों को स्वयं रचनाकार को ले जाने पर विचार कर सकते हैं।

0

मैं दो संभावित मुद्दों देखें:

  • तरीकों क्या आप initializeCanvas निजी या फाइनल में कहते हैं? यदि वे नहीं हैं, तो उप-वर्ग के लिए उन्हें ओवरराइड करना संभव है और अनजाने में आपके कन्स्ट्रक्टर को तोड़ना संभव है।

  • क्या आप drawBoundaries विधि में ग्राफिक्स परिचालन कर रहे हैं? एक रचनाकार के लिए एक वैध वस्तु बनाने के लिए केवल न्यूनतम आवश्यक करने के लिए यह अच्छा अभ्यास है। क्या वे परिचालन कैनवास के लिए आवश्यक प्रारंभिक स्थिति रखने के लिए आवश्यक हैं?

2

आपको कभी भी कन्स्ट्रक्टर में गैर-अंतिम विधियों को कॉल नहीं करना चाहिए। प्रभावी जावा एक अच्छा काम बताता है क्यों, लेकिन मूल रूप से आपका ऑब्जेक्ट कन्स्ट्रक्टर रिटर्न से पहले स्थिर स्थिति में नहीं है। यदि आपका कन्स्ट्रक्टर उप-वर्ग द्वारा ओवरराइड किए गए तरीकों को कॉल करता है, तो आप अजीब, अपरिभाषित व्यवहार प्राप्त कर सकते हैं।

this answer भी देखें।

+1

विधि 'निजी' है, इसलिए इसे उप-वर्ग द्वारा ओवरराइट नहीं किया जा सका। क्या मैं कुछ भूल रहा हूँ? – kunal

+0

हां, आपकी निजी विधि अन्य विधियों को बुला रही है। क्या वे सभी विधियां निजी और/या अंतिम हैं? –

+0

मेरे पास कुछ साल पहले नौकरी साक्षात्कार था, जहां उन्होंने मुझसे पूछा कि कोड के टुकड़े में क्या गलत है। स्पष्ट लोगों का जिक्र करने के बाद, मैंने उनसे कहा कि वहां एक संभावित डिजाइन मुद्दा था, क्योंकि अंगूठे के नियम के रूप में हम कभी भी कन्स्ट्रक्टर से निजी तरीकों को नहीं बुलाते थे। - यह आधे घंटे की चर्चा में बढ़ गया, क्योंकि साक्षात्कारकर्ता ने मुझे विश्वास नहीं किया। अंत में, उन्होंने मुझे नौकरी नहीं दी। जाहिर है, उसने यह व्यक्तिगत लिया। साक्षात्कारकर्ता के अनुसार: "मैं ओओपी नहीं समझता"। :-) - लेकिन "प्रभावी जावा" जैसी पुस्तक का संदर्भ होना अच्छा है। यह एक स्पष्ट जीत होगी। – bvdb

0

यह निर्भर करता है।

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

एक दूसरी समस्या यदि आपके initalizeCanvas विधि में से कुछ विधियों को लगता है कि वे पूरी तरह से प्रारंभ होने से पहले वर्तमान ऑब्जेक्ट को "प्रकाशित" करते हैं।यह संभावित रूप से समस्याग्रस्त है यदि एप्लिकेशन बहु-थ्रेडेड है, और परिणामस्वरूप अन्य फ़ील्ड पुराने क्षेत्र मान देख सकते हैं।

0

एक निजी इनिट फ़ंक्शन उपयोगी हो सकता है यदि आपके पास एकाधिक कन्स्ट्रक्टर हैं जहां कुछ पैरामीटर डिफॉल्ट या अनुमानित हैं। सबकुछ निर्धारित होने के बाद, एक निजी इनिट फ़ंक्शन ऑब्जेक्ट में भर जाता है।

एक-कन्स्ट्रक्टर क्लास में, शायद नहीं।

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