OOP कोडिंग स्टाइल: कंस्ट्रक्टर पर सब कुछ इनिशियलाइज़ करें?


14

मैं अभी भी खुद को प्रशिक्षु प्रोग्रामर के रूप में मानता हूं, इसलिए मैं हमेशा विशिष्ट प्रोग्रामिंग के लिए "बेहतर" तरीका सीखना चाहता हूं। आज, मेरे सहकर्मी ने तर्क दिया है कि मेरी कोडिंग शैली कुछ अनावश्यक काम करती है, और मैं दूसरों से राय सुनना चाहता हूं। आमतौर पर, जब मैं ओओपी भाषा (आमतौर पर सी ++ या पायथन) में एक कक्षा डिजाइन करता हूं, तो मैं आरंभीकरण को अलग-अलग भागों में अलग कर दूंगा:

class MyClass1 {
public:
    Myclass1(type1 arg1, type2 arg2, type3 arg3);
    initMyClass1();
private:
    type1 param1;
    type2 param2;
    type3 param3;
    type4 anotherParam1;
};

// Only the direct assignments from the input arguments are done in the constructor
MyClass1::myClass1(type1 arg1, type2 arg2, type3 arg3)
    : param1(arg1)
    , param2(arg2)
    , param3(arg3)
    {}

// Any other procedure is done in a separate initialization function 
MyClass1::initMyClass1() {
    // Validate input arguments before calculations
    if (checkInputs()) {
    // Do some calculations here to figure out the value of anotherParam1
        anotherParam1 = someCalculation();
    } else {
        printf("Something went wrong!\n");
        ASSERT(FALSE)
    }
}

(या, अजगर समकक्ष)

class MyClass1:

    def __init__(self, arg1, arg2, arg3):
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3
        #optional
        self.anotherParam1 = None

    def initMyClass1():
        if checkInputs():
            anotherParam1 = someCalculation()
        else:
            raise "Something went wrong!"

इस दृष्टिकोण के बारे में आपकी क्या राय है? क्या मुझे आरंभीकरण प्रक्रिया को विभाजित करने से बचना चाहिए? सवाल केवल सी ++ और पायथन तक ही सीमित नहीं है, और अन्य भाषाओं के उत्तर भी सराहना करते हैं।



2
इन्हें भी देखें: stackoverflow.com/questions/33124542/…
Doc Brown


आप आमतौर पर ऐसा क्यों करते हैं? आदत? क्या आपने कभी ऐसा करने का कारण दिया?
जेएफओ

@ जेफ़ो मुझे यह आदत तब मिली जब मैं एमएफसी लाइब्रेरी के साथ जीयूआई बनाने के लिए काम कर रहा था। अधिकांश UI से संबंधित कक्षाएं, जैसे कि CApp, CWindow, CDlg, और इसके आगे, एक OnInit () फ़ंक्शन हैं जिनके साथ आप ओवरराइट कर सकते हैं, जो उनके सह-संदेश संदेशों का जवाब देता है।
Caladbolgll

जवाबों:


28

हालांकि कभी-कभी यह समस्याग्रस्त होता है, निर्माणकर्ता में सब कुछ शुरू करने के कई फायदे हैं:

  1. अगर वहाँ जा रहा है एक त्रुटि हो, यह जितनी जल्दी हो सके और निदान करने के लिए सबसे आसान है। उदाहरण के लिए, यदि नल अमान्य तर्क मान है, तो परीक्षण करें और निर्माता में विफल रहें।
  2. ऑब्जेक्ट हमेशा एक मान्य स्थिति में होता है। एक सहकर्मी गलती नहीं कर सकता है और कॉल करना न भूलें initMyClass1()क्योंकि यह नहीं है"सबसे सस्ता, सबसे तेज़ और सबसे विश्वसनीय घटक वे हैं जो वहां नहीं हैं।"
  3. यदि यह समझ में आता है, तो वस्तु को अपरिवर्तनीय बनाया जा सकता है जिसके बहुत सारे फायदे हैं।

2

अमूर्त के बारे में सोचो जो आप अपने उपयोगकर्ताओं को प्रदान कर रहे हैं।

क्यों कुछ है कि एक शॉट में दो में किया जा सकता है विभाजित?

अतिरिक्त आरंभीकरण केवल प्रोग्रामर के लिए आपके एपीआई का उपयोग करने के लिए याद रखने के लिए कुछ अतिरिक्त है, और गलत होने के लिए और अधिक प्रदान करता है यदि वे इसे सही नहीं करते हैं, लेकिन इस अतिरिक्त बोझ के लिए उनके लिए क्या मूल्य है?

आप मृत सरल, आसान उपयोग प्रदान करना चाहते हैं, गलत सार निकालना मुश्किल है। याद करने के लिए / हुप्स को याद रखने के लिए आभारी चीजों के बिना प्रोग्रामिंग काफी कठिन है। आप अपने एपीआई उपयोगकर्ताओं (भले ही यह सिर्फ आप अपने एपीआई का उपयोग कर रहे हैं) को सफलता के गर्त में गिराना चाहते हैं


1

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


0

ऐसे मामले हैं जहां ऑब्जेक्ट में बहुत अधिक आरंभीकरण होता है जिसे दो श्रेणियों में विभाजित किया जा सकता है:

  1. विशेषताएँ जो या तो अपरिवर्तनीय हैं या उन्हें रीसेट करने की आवश्यकता नहीं है।

  2. उन विशेषताओं को जो मूल शर्तों (या टेम्प्लेटाइज्ड वैल्यूज़) को वापस करने की आवश्यकता हो सकती है, जो नौकरी पूरी करने के बाद कुछ शर्त के आधार पर होती है, एक सॉफ्ट रीसेट की तरह। जैसे कनेक्शन-पूल में कनेक्शन।

इनिशियलाइज़ऑब्जेक्ट () के अनुसार, इनिशियलाइज़ेशन के दूसरे भाग को एक अलग फंक्शन में रखा जा रहा है, जिसे Ctor में कहा जा सकता है।

एक ही फ़ंक्शन को बाद में कॉल किया जा सकता है यदि ऑब्जेक्ट को त्यागने और पुनः बनाए बिना एक नरम रीसेट की आवश्यकता होती है।


0

जैसा कि दूसरों ने कहा है, यह आमतौर पर कंस्ट्रक्टर में शुरू करने के लिए एक अच्छा विचार है।

हालांकि, ऐसे कारण हैं जो विशिष्ट मामलों में लागू नहीं हो सकते हैं या नहीं भी कर सकते हैं।

गलती संभालना

बहुत सी भाषाओं में, एक रचनाकार में त्रुटि का संकेत करने का एकमात्र तरीका अपवाद उठाना है।

यदि आपके इनिशियलाइज़ेशन में त्रुटि उठाने का एक उचित मौका है, जैसे कि इसमें IO शामिल है या इसके पैरामीटर उपयोगकर्ता इनपुट हो सकते हैं, तो आपके लिए खुला एकमात्र तंत्र अपवाद उठाना है। कुछ मामलों में, यह वह नहीं हो सकता है जो आप चाहते हैं और यह एक अलग इनिशियलाइज़ेशन फ़ंक्शन के लिए त्रुटि प्रवण कोड को अलग करने के लिए अधिक समझ में आता है।

संभवतः इसका सबसे सामान्य उदाहरण C ++ में है यदि परियोजना / संगठनात्मक मानक अपवादों को बंद करना है।

राज्य मशीन

यह वह स्थिति है जहां आप एक ऑब्जेक्ट को मॉडलिंग कर रहे हैं जिसमें स्पष्ट राज्य परिवर्तन हैं। उदाहरण के लिए, एक फ़ाइल या सॉकेट जिसे खोला और बंद किया जा सकता है।

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

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.