सभी डेवलपर्स की तरह, मुझे अक्सर यह कथन पढ़ना और सुनना था कि "रचना हमेशा विरासत से बेहतर होती है।" शायद बहुत बार भी। हालांकि, मैं विश्वास पर कुछ भी करने के लिए इच्छुक नहीं हूं, तो चलो यह पता करें कि क्या ऐसा है।
तो, विरासत पर रचना के फायदे क्या हैं?
1. कोई नाम संघर्ष नहीं है जो विरासत के साथ संभव है।
2. रनटाइम में एकत्रित वस्तु को बदलने
की क्षमता।
3. कुल वस्तु सहित वर्ग से प्राप्त कक्षाओं में कुल वस्तु का पूर्ण प्रतिस्थापन।
पिछले दो मामलों में, यह अत्यधिक वांछनीय है कि बदली सकल वस्तुओं का एक सामान्य इंटरफ़ेस है। और तीसरे में - ताकि ऐसी वस्तु वापस करने की विधि आभासी हो।
यदि हम उदाहरण के लिए, C # पर विचार करते हैं, जो एकाधिक वंशानुक्रम का समर्थन नहीं करता है, लेकिन आपको कई इंटरफ़ेस से इनहेरिट करने और इन इंटरफ़ेस के लिए विस्तार विधियाँ बनाने की अनुमति देता है, तो दो और फायदे हैं (इस मामले में हम केवल
व्यवहार के बारे में बात कर सकते
हैं ("रणनीति" पैटर्न के ढांचे में
एल्गोरिदम ) "):
4. एकत्रित व्यवहार (एल्गोरिथम) में अन्य वस्तुएँ शामिल हो सकती हैं। जो, विशेष रूप से, एकत्रीकरण के माध्यम से अन्य व्यवहार का पुन: उपयोग करने की अनुमति देता है।
5. एकत्रीकरण के दौरान, कार्यान्वयन के एक निश्चित भाग को छिपाना संभव है, साथ ही व्यवहार के लिए आवश्यक प्रारंभिक पैरामीटर, उन्हें कंस्ट्रक्टर के माध्यम से पारित करके (विरासत के दौरान, व्यवहार को अपने स्वयं के इंटरफ़ेस के तरीकों / गुणों के माध्यम से अनुरोध करना होगा)।
लेकिन विपक्ष के बारे में क्या? क्या वे वास्तव में चले गए हैं?
1. इसलिए, अगर हमें बाहर से व्यवहार को बदलने की क्षमता की आवश्यकता है, तो रचना, विरासत के साथ तुलना में, व्यवहार की वस्तु और इसका उपयोग करने वाली वस्तु के बीच मौलिक रूप से भिन्न प्रकार का संबंध है। यदि हमें अमूर्त व्यवहार से विरासत में मिला है, तो हमारे पास 1: 1 का अनुपात है, तो एकत्रीकरण और बाहर से व्यवहार की स्थापना की संभावना के साथ, हमें 1: कई अनुपात मिलता है। यानी एक ही व्यवहार ऑब्जेक्ट का उपयोग कई स्वामी ऑब्जेक्ट द्वारा किया जा सकता है। इसके कारण इन स्वामी ऑब्जेक्ट्स के लिए एक सामान्य व्यवहार स्थिति के साथ समस्याएँ होती हैं।
इस स्थिति को बाहर से व्यवहार की स्थापना पर रोक लगाने या इसे सौंपने से हल किया जा सकता है, उदाहरण के लिए, सामान्य विधि के लिए:
void SetBehavior<TBehavior>()
जिससे मालिक वस्तु के अलावा किसी अन्य व्यक्ति द्वारा व्यवहार के निर्माण पर रोक लगाई जा सके। हालाँकि, हम व्यवहार "कहीं और" के उपयोग पर रोक नहीं लगा सकते हैं। कचरा बीनने वाले (जीसी) के बिना भाषाओं में, यह समझने योग्य समस्याएं पैदा करता है। बेशक, ऐसी भाषाओं में, आप गैर-कानूनी रूप से मालिक वस्तु का भी उल्लेख कर सकते हैं, लेकिन अलग-अलग व्यवहार वाली वस्तुओं को दाईं ओर और बाईं ओर वितरित करके, हमें एक अपवाद प्राप्त करने के लिए कई गुना अधिक संभावनाएं मिलती हैं।
2. एकत्रीकरण (और यह, शायद, मुख्य बारीकियों है) पहली जगह में विरासत से अलग है कि एकत्रित वस्तु एक मालिक वस्तु नहीं है और इसके बारे में जानकारी शामिल नहीं है। अक्सर ऐसी परिस्थितियां होती हैं जब कोड जो व्यवहार के साथ इंटरैक्ट करता है, उसे स्वामी को स्वयं ऑब्जेक्ट की आवश्यकता होती है (उदाहरण के लिए, इसके बारे में जानकारी प्राप्त करने के लिए कि उसके अन्य व्यवहार क्या हैं)।
इस स्थिति में, हमें या तो कोड (जैसे ऑब्जेक्ट या शून्य *) के लिए एक अनपेक्षित ऑब्जेक्ट पास करना होगा, या मालिक ऑब्जेक्ट (कुछ IBehaviorOwner) के लिए एक अतिरिक्त इंटरफ़ेस बनाना होगा, या व्यवहार में स्वामी ऑब्जेक्ट के लिए एक परिपत्र संदर्भ संग्रहीत करना होगा। यह स्पष्ट है कि इनमें से प्रत्येक विकल्प में इसकी कमियां हैं और आगे कोड को जटिल करता है। इसके अलावा, विभिन्न प्रकार के व्यवहार एक-दूसरे पर निर्भर हो सकते हैं (और यह पूरी तरह से स्वीकार्य है, खासकर यदि वे किसी प्रकार के बंद स्व-निहित मॉड्यूल में हैं)।
3. खैर, अंतिम माइनस निश्चित रूप से प्रदर्शन है। यदि बहुत सारे ऑब्जेक्ट-ओनर हैं, तो एक ऑब्जेक्ट के बजाय दो या अधिक ऑब्जेक्ट्स का निर्माण और विनाश किसी का ध्यान नहीं जा सकता है।
यह पता चला है कि बयान "रचना हमेशा विरासत से बेहतर होती है" कुछ मामलों में विवादास्पद है और एक हठधर्मिता नहीं होनी चाहिए। यह उन भाषाओं के लिए विशेष रूप से सच है जो कई वंशानुक्रम की अनुमति देते हैं और जीसी नहीं होते हैं। यदि किसी भी स्थिति में उपरोक्त फायदे महत्वपूर्ण नहीं हैं, और यह पहले से ही ज्ञात है कि कुछ प्रकार के साथ काम करते समय आप उनका उपयोग नहीं कर पाएंगे, तो आपको अभी भी विरासत के विकल्प पर विचार करना चाहिए।