कम्पोजीशन ओवर इनहेरिटेंस

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

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

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

इनहेरिटेंस
सी ++ में एक उदाहरण इस प्रकार है,

class Object

{ public: virtual void update { // no-op }    virtual void draw { // no-op }    virtual void collide(Object objects[]) { // no-op } }; class Visible : public Object {    Model* model; public: virtual void draw override { // code to draw a model at the position of this object } }; class Solid : public Object { public: virtual void collide(Object objects[]) override { // code to check for and react to collisions with other objects } }; class Movable : public Object { public: virtual void update override { // code to update the position of this object } };

फिर, मान लीजिए कि हमारे पास ये काँक्रीट क्लास इस प्रकार है

ध्यान दें कि मल्टीपल इनहेरिटेंस खतरनाक रूप में होते है, यदि इसे सावधानी से  प्रयुक्त नहीं किया गया  क्योंकि इससे मल्टीपल इनहेरिटेंस डायमंड की समस्या हो सकती है। इसका एक समाधान यह है कि प्रत्येक आवश्यक संयोजन के लिए विजिबल एंड सॉलिड विजिबल एंड मूवेबल विजिबल एंड सॉलिड एंड मूवेबल इत्यादि जैसी क्लासेस बनाई जाएं चूंकि, यह बड़ी मात्रा में दोहराव वाले कोड की ओर ले जाता है। C ++ मल्टीपल इनहेरिटेंस की डायमंड प्रॉब्लम को हल करने के लिए वर्चुअल इनहेरिटेंस  का उपयोग करता है।
 * क्लास प्लेयर - जो सॉलिड, मूवेबल और विजिबल है
 * क्लास क्लाउड - जो मूववेबल और दृश्यमान रूप में होती है, लेकिन ठोस नहीं होती है
 * क्लास बिल्डिंग - जो सॉलिड और विजिबल रूप में होती है, लेकिन मूवेबल नहीं होती है
 * क्लास ट्रैप - जो ठोस रूप में होती है, लेकिन न तो दिखाई देती है और न ही चल सकती है

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

नामक एक अमूर्त क्लास का परिचय दें VisibilityDelegate, उपक्लासेस के साथ NotVisible और Visible, जो किसी वस्तु को खींचने का साधन प्रदान करता है:

<वाक्यविन्यास लैंग = सीपीपी> क्लास दृश्यता प्रतिनिधि { जनता: आभासी शून्य ड्रा = 0; };

क्लास नॉटविजिबल: पब्लिक विजिबिलिटी डेलिगेट { जनता: आभासी शून्य ड्रा ओवरराइड { // नो-ऑप } };

क्लास दृश्यमान: सार्वजनिक दृश्यता प्रतिनिधि { जनता: आभासी शून्य ड्रा ओवरराइड { // कोड इस वस्तु की स्थिति पर एक मॉडल बनाने के लिए } }; 

नामक एक अमूर्त क्लास का परिचय दें UpdateDelegate, उपक्लासेस के साथ NotMovable और Movable, जो किसी वस्तु को स्थानांतरित करने का साधन प्रदान करता है:

<वाक्यविन्यास लैंग = सीपीपी> क्लास अद्यतन प्रतिनिधि { जनता: आभासी शून्य अद्यतन = 0; };

क्लास नॉटमूवेबल: पब्लिक अपडेटडिलेगेट { जनता: आभासी शून्य अद्यतन ओवरराइड { // नो-ऑप } };

क्लास मूवेबल: पब्लिक अपडेटडिलेगेट { जनता: आभासी शून्य अद्यतन ओवरराइड { // कोड इस वस्तु की स्थिति को अद्यतन करने के लिए } }; 

नामक एक अमूर्त क्लास का परिचय दें CollisionDelegate, उपक्लासेस के साथ NotSolid और Solid, जो किसी वस्तु से टकराने का साधन प्रदान करता है:

<वाक्यविन्यास लैंग = सीपीपी> क्लास टकराव प्रतिनिधि { जनता: आभासी शून्य टक्कर (ऑब्जेक्ट ऑब्जेक्ट्स []) = 0; };

क्लास नॉटसॉलिड: पब्लिक कोलिशनडिलेगेट { जनता: आभासी शून्य टक्कर (ऑब्जेक्ट ऑब्जेक्ट्स []) ओवरराइड { // नो-ऑप } };

क्लास सॉलिड: पब्लिक कोलिशनडिलेगेट { जनता: आभासी शून्य टक्कर (ऑब्जेक्ट ऑब्जेक्ट्स []) ओवरराइड { // अन्य वस्तुओं के साथ टकराव की जांच करने और प्रतिक्रिया करने के लिए कोड } }; 

अंत में, नाम की एक क्लासेस का परिचय दें Object इसकी दृश्यता को नियंत्रित करने के लिए सदस्यों के साथ (ए VisibilityDelegate), चलनशीलता (एक का उपयोग करके UpdateDelegate), और दृढ़ता (ए का उपयोग करके CollisionDelegate). इस क्लास में ऐसी विधियाँ हैं जो इसके सदस्यों को सौंपती हैं, उदा। update बस पर एक विधि कहते हैं UpdateDelegate:

<वाक्यविन्यास लैंग = सीपीपी> क्लास वस्तु {   दृश्यता प्रतिनिधि* _v; UpdateDelegate* _u; CollisionDelegate* _c;

जनता: ऑब्जेक्ट (दृश्यता प्रतिनिधि * v, अद्यतन प्रतिनिधि * यू, टकराव प्रतिनिधि * सी) : _वी (वी) , _तुम तुम)      , _सी (सी)    {}

शून्य अद्यतन { _यू-> अपडेट ; }

शून्य ड्रा { _v-> ड्रा ; }

शून्य टक्कर (ऑब्जेक्ट ऑब्जेक्ट्स []) { _c-> टकराना (ऑब्जेक्ट्स); } }; 

फिर, ठोस क्लासेस एं दिखेंगी:

<वाक्यविन्यास लैंग = सीपीपी> क्लास प्लेयर: पब्लिक ऑब्जेक्ट { जनता: खिलाड़ी : ऑब्जेक्ट (नया दृश्यमान, नया चल , नया ठोस ) {}

// ... };

क्लास धुआँ: सार्वजनिक वस्तु { जनता: धुआँ : ऑब्जेक्ट (नया दृश्यमान, नया मूवेबल , नया नॉटसॉलिड ) {}

// ... }; 

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

कुछ भाषाएँ, विशेष रूप से गो (प्रोग्रामिंग भाषा) और जंग (प्रोग्रामिंग भाषा), विशेष रूप से प्रकार की रचना का उपयोग करें।

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

उदाहरण के लिए, नीचे दिए गए सी # कोड में, वेरिएबल्स और विधियों के Employee बेस क्लास द्वारा इनहेरिटेंस में मिला है HourlyEmployee और SalariedEmployee व्युत्पन्न उपक्लास । केवल Pay विधि को प्रत्येक व्युत्पन्न उपक्लास  द्वारा कार्यान्वित (विशेष) करने की आवश्यकता है। अन्य विधियों को आधार क्लास  द्वारा ही  प्रयुक्त किया जाता है, और इसके सभी व्युत्पन्न उपक्लासेस द्वारा साझा किया जाता है; उन्हें फिर से  प्रयुक्त करने (ओवरराइड) या यहां तक ​​​​कि उपक्लास  परिलैंग्वेज में उल्लेख करने की आवश्यकता नहीं है।

<वाक्यविन्यास प्रकाश लैंग = csharp> // बेस क्लास सार्वजनिक सार क्लास कर्मचारी {   // गुण संरक्षित स्ट्रिंग नाम {प्राप्त करें; तय करना; } संरक्षित इंट आईडी {प्राप्त करें; तय करना; } संरक्षित दशमलव भुगतान दर {प्राप्त करें; तय करना; } संरक्षित int घंटे काम किया { प्राप्त करें; }

// वर्तमान वेतन अवधि के लिए भुगतान प्राप्त करें सार्वजनिक सार दशमलव वेतन ; }

// व्युत्पन्न उपक्लास पब्लिक क्लास प्रति घंटा कर्मचारी: कर्मचारी {   // वर्तमान वेतन अवधि के लिए भुगतान प्राप्त करें सार्वजनिक ओवरराइड दशमलव वेतन {       // काम किया गया समय घंटों में है वापसी के घंटे काम * वेतन दर; } }

// व्युत्पन्न उपक्लास सार्वजनिक क्लास के वेतनभोगी कर्मचारी: कर्मचारी {   // वर्तमान वेतन अवधि के लिए भुगतान प्राप्त करें सार्वजनिक ओवरराइड दशमलव वेतन {       // वेतन दर प्रति घंटे की दर के अतिरिक्त  वार्षिक वेतन है वापसी के घंटे काम * वेतन दर / 2087; } } 

कमियों से बचना
ट्रेट्स (कंप्यूटर साइंस), mixin्स, (टाइप) एम्बेडिंग, या प्रोटोकॉल (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) एक्सटेंशन का उपयोग करके इस कमी से बचा जा सकता है।

कुछ भाषाएँ इसे कम करने के लिए विशिष्ट साधन प्रदान करती हैं:


 * सी शार्प (प्रोग्रामिंग लैंग्वेज) | सी # संस्करण 8.0 के बाद से डिफ़ॉल्ट इंटरफ़ेस विधि प्रदान करता है जो शरीर को इंटरफ़ेस सदस्य को परिभाषित करने की अनुमति देता है।
 * डी (प्रोग्रामिंग भाषा) एक स्पष्ट उपनाम प्रदान करता है, यह घोषणा एक प्रकार के भीतर हर विधि और किसी अन्य निहित प्रकार के सदस्य को अग्रेषित कर सकती है।
 * डार्ट (प्रोग्रामिंग भाषा) डिफ़ॉल्ट कार्यान्वयन के साथ मिक्सिन प्रदान करता है जिसे साझा किया जा सकता है।
 * गो (प्रोग्रामिंग लैंग्वेज) टाइप एम्बेडिंग अग्रेषण विधियों की आवश्यकता से बचाती है।
 * जावा (प्रोग्रामिंग भाषा) संस्करण 8 के बाद से डिफ़ॉल्ट इंटरफ़ेस विधियाँ प्रदान करता है। प्रोजेक्ट लोम्बोक प्रतिनिधिमंडल का समर्थन करता है @Delegate प्रत्यायोजित क्षेत्र से सभी विधियों के नामों और प्रकारों को कॉपी करने और बनाए रखने के अतिरिक्त क्षेत्र पर एनोटेशन। * जूलिया (प्रोग्रामिंग भाषा) मैक्रोज़ का उपयोग अग्रेषण विधियों को उत्पन्न करने के लिए किया जा सकता है। Lazy.jl जैसे कई कार्यान्वयन सम्मलित   हैं और TypedDelegation.jl।
 * कोटलिन (प्रोग्रामिंग भाषा) में लैंग्वेज सिंटैक्स में डेलिगेशन पैटर्न सम्मलित है।
 * PHP लक्षणों (कंप्यूटर विज्ञान) का समर्थन करता है।
 * राकू (प्रोग्रामिंग भाषा) एक प्रदान करता है handles विधि अग्रेषण की सुविधा के लिए विशेषता।
 * रस्ट (प्रोग्रामिंग लैंग्वेज) डिफ़ॉल्ट कार्यान्वयन के साथ लक्षण प्रदान करता है।
 * स्काला (प्रोग्रामिंग भाषा) (संस्करण 3 के बाद से) किसी वस्तु के चयनित सदस्यों के लिए उपनामों को परिभाषित करने के लिए एक निर्यात खंड प्रदान करता है।
 * स्विफ्ट (प्रोग्रामिंग भाषा) एक्सटेंशन का उपयोग किसी प्रोटोकॉल के डिफ़ॉल्ट कार्यान्वयन को परिभाषित करने के लिए किया जा सकता है, बजाय किसी व्यक्तिगत प्रकार के कार्यान्वयन के।

अनुभवजन्य अध्ययन
2013 में 93 ओपन सोर्स जावा प्रोग्राम (भिन्न -भिन्न आकार के) के एक अध्ययन में पाया गया कि:

"While there is not huge opportunity to replace inheritance with composition (...), the opportunity is significant (median of 2% of uses [of inheritance] are only internal reuse, and a further 22% are only external or internal reuse).

Our results suggest there is no need for concern regarding abuse of inheritance (at least in open-source Java software), but they do highlight the question regarding use of composition versus inheritance. If there are significant costs associated with using inheritance when composition could be used, then our results suggest there is some cause for concern."

यह भी देखें

 * प्रतिनिधिमंडल पैटर्न
 * लिस्कोव प्रतिस्थापन सिद्धांत
 * वस्तु उन्मुख डिजाइन
 * वस्तु रचना
 * भूमिका-उन्मुख प्रोग्रामिंग
 * राज्य पैटर्न
 * रणनीति पैटर्न