ऐसे कंस्ट्रक्टर कैसे लिखें जो किसी ऑब्जेक्ट को ठीक से फेल करने में विफल हो सकते हैं


12

कभी-कभी आपको एक रचनाकार लिखने की ज़रूरत होती है जो विफल हो सकती है। उदाहरण के लिए, मान लीजिए कि मैं किसी फ़ाइल पथ के साथ किसी वस्तु को त्वरित करना चाहता हूं, जैसे कुछ

obj = new Object("/home/user/foo_file")

जब तक पथ एक उपयुक्त फ़ाइल को इंगित करता है सब कुछ ठीक है। लेकिन अगर स्ट्रिंग एक वैध मार्ग नहीं है तो चीजों को तोड़ देना चाहिए। पर कैसे?

आप ऐसा कर सकते हैं:

  1. एक अपवाद फेंक दो
  2. वापसी अशक्त वस्तु (यदि आपकी प्रोग्रामिंग भाषा कंस्ट्रक्टरों को मान वापस करने की अनुमति देती है)
  3. एक वैध वस्तु लौटाएं लेकिन एक झंडे के साथ जो यह दर्शाता है कि उसका रास्ता ठीक से सेट नहीं किया गया था (ugh)
  4. अन्य?

मुझे लगता है कि विभिन्न प्रोग्रामिंग भाषाओं के "सर्वोत्तम अभ्यास" इसे अलग तरीके से लागू करेंगे। उदाहरण के लिए, मुझे लगता है कि ObjC पसंद (2)। लेकिन (2) सी ++ में लागू करना असंभव होगा जहां निर्माणकर्ताओं को रिटर्न प्रकार के रूप में शून्य होना चाहिए। उस स्थिति में मैं इसे लेता हूं कि (1) का उपयोग किया जाता है।

अपनी पसंद की प्रोग्रामिंग भाषा में आप यह दिखा सकते हैं कि आप इस समस्या को कैसे संभालेंगे और समझाएँगे क्यों?


1
जावा में अपवाद इसे संभालने का एक तरीका है।
महमूद होसाम

C ++ कंस्ट्रक्टर्स वापस नहीं आते void- वे एक ऑब्जेक्ट वापस करते हैं।
गैबलिन

6
@ गैब्लिन: वास्तव में, यह सख्ती से सच भी नहीं है। मेमोरी को आवंटित करने के लिए newकॉल operator newकरता है, फिर इसे भरने के लिए कंस्ट्रक्टर। कंस्ट्रक्टर कुछ भी नहीं लौटाता है, और newउस पॉइंटर को लौटा देता है जो उसे मिला है operator new। चाहे "कुछ भी वापस नहीं करता है" "रिटर्न void" का अर्थ है, हालांकि, कब्रों के लिए है।
जॉन पूर्डी

@ जॉन पंडी: एचएम, उचित लगता है। अच्छा निर्णय।
गाब्लिन

जवाबों:


8

गंदा काम करने के लिए किसी निर्माता पर भरोसा करना कभी अच्छा नहीं होता। इसके अलावा, यह किसी अन्य प्रोग्रामर के लिए भी स्पष्ट नहीं है कि कंस्ट्रक्टर में काम हो रहा है या नहीं, जब तक कि वहाँ स्पष्ट प्रलेखन ऐसा न हो (और वर्ग के उपयोगकर्ता ने इसे पढ़ा हो या ऐसा बताया गया हो)।

उदाहरण के लिए (C # में):

public Sprite
{
    public Sprite(string filename)
    {
    }
}

यदि उपयोगकर्ता सीधे फ़ाइल लोड नहीं करना चाहता है तो क्या होगा? यदि वे फ़ाइल की ऑन-डिमांड कैशिंग करना चाहते हैं तो क्या होगा? वे नहीं कर सकते। आप bool loadFileकंस्ट्रक्टर में एक तर्क देने के बारे में सोच सकते हैं , लेकिन फिर यह गड़बड़ कर देता है क्योंकि आपको अब भीLoad() फ़ाइल लोड करने के लिए एक विधि की आवश्यकता है ।

वर्तमान परिदृश्य को देखते हुए, ऐसा करने के लिए यह वर्ग के उपयोगकर्ताओं के लिए अधिक लचीला और स्पष्ट होने जा रहा है:

Sprite sprite = new Sprite();
sprite.Load("mario.png");

या वैकल्पिक रूप से (संसाधन की तरह कुछ के लिए):

Sprite sprite = new Sprite();
sprite.Source = "mario.png";
sprite.Cache();

// On demand caching of file contents.
public void Cache()
{
     if (image == null)
     {
         try
         {
             image = new Image.FromFile(Source);
         }
         catch(...)
         {
         }
     }
}

आपके मामले में यदि लोड (..) विफल है, तो हमारे पास पूरी तरह से बेकार वस्तु है। मुझे यकीन नहीं है कि मैं किसी स्प्राइट के बिना स्प्राइट चाहता हूं ... लेकिन सवाल असली सवाल से अधिक पवित्र विषय की तरह दिखता है :)
एव्टोमेटन

7

जावा में, आप अपवाद का उपयोग कर सकते हैं या फ़ैक्टरी पैटर्न का उपयोग कर सकते हैं, जो आपको अशक्त होने की अनुमति देगा।

स्काला में, आप फ़ैक्टरी विधि से एक विकल्प [फू] लौटा सकते हैं। यह जावा में भी काम करेगा, लेकिन अधिक बोझिल होगा।


.NET भाषाओं में अपवाद या फ़ैक्टरी का उपयोग करना।
बेथ व्हाइटजेल

3

एक अपवाद फेंक दें।

यदि आप इसे वापस कर सकते हैं (और इसे चेक नहीं किया जाएगा) के लिए अशक्त होने की आवश्यकता है

यह वह है जो अपवादों की जाँच करता है। तुम्हें पता है कि यह विफल हो सकता है। कॉल करने वालों को इसे संभालना होगा।


3

में सी ++ , कंस्ट्रक्टर्स वर्ग के / इनिशियलाइज़ सदस्यों बनाने के लिए इस्तेमाल कर रहे हैं।

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

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

यदि यह व्यवहार का चयन करने के लिए आप पर निर्भर है, तो त्रुटियों को संभालने के लिए अपवाद C ++ तरीका है और जब आप कर सकते हैं तो आपको उनका उपयोग करना चाहिए।


1

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


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

2
@kevin: वस्तु पर निर्भर करता है। विफलताएं संभवत: बाहरी संसाधनों के कारण होंगी, इसलिए कोई संस्था इरादा दर्ज करना चाहती है (उदाहरण फ़ाइल नाम) लेकिन पूरी तरह से शुरू करने के लिए बार-बार प्रयास करने की अनुमति दें। मान ऑब्जेक्ट के लिए मैं संभवतः एक त्रुटि की रिपोर्ट करने की ओर झुकूंगा जो अंतर्निहित त्रुटि को पकड़ सकती है, इसलिए संभवतः एक लिपटे (लिपटे हुए) अपवाद को फेंकना।
डेव

-4

मैं कंस्ट्रक्टर में किसी भी वर्ग या सूची को इनिशियलाइज़ नहीं करना चाहता। जब भी आपको आवश्यकता हो एक वर्ग या सूची को आरम्भ करें। उदाहरण के लिए।

public class Test
{
    List<Employee> test = null;
}

यह मत करो

public class Test
{
    List<Employee> test = null;

    public Test()
    {
        test = new List<Employee>();
    }
}

इसके बजाय जब आवश्यक हो तो इनिशियलाइज़ करें।

public class Test
{
    List<Employee> emp = null;

    public Test()
    { 
    }

    public void SomeFunction()
    {
         emp = new List<Employee>();
    }
}

1
यह खराब सलाह है। आपको ऑब्जेक्ट को अमान्य स्थिति में नहीं होने देना चाहिए। यही कंस्ट्रक्टर के लिए है। यदि आपको जटिल तर्क की आवश्यकता है तो फैक्टरी पैटर्न का उपयोग करें।
एलेक्सफॉक्सगिल

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