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

ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग ऊप में इनहेरिटेंस पर रचना सिद्धांत या सम्मिश्र पुनः प्रयोग सिद्धांत के रूप में होता है तथा क्लासेस को बहुरूपता कंप्यूटर विज्ञान व्यवहार और कोड का पुन: उपयोग करना चाहिए तथा उनकी संरचना द्वारा अन्य क्लासेस के उदाहरण देना चाहिए  जो किसी आधार या पैरेंट क्लास से प्राप्त इनहेरिटेंस कंप्यूटर विज्ञान के अतिरिक्त वांछित कार्यकार्यात्मकता को कार्यान्वित करते हैं। यह ऊप का प्रायः सिद्धांत है, जिसमे कि प्रभावशाली पुस्तक डिजाइन पैटर्न्स 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 ++ मल्टीपल इनहेरिटेंस की डायमंड प्रॉब्लम को हल करने के लिए वर्चुअल इनहेरिटेंस  का उपयोग करता है।
 * क्लास प्लेयर - जो सॉलिड, मूवेबल और विजिबल है
 * क्लास क्लाउड - जो मूववेबल और दृश्यमान रूप में होती है, लेकिन ठोस नहीं होती है
 * क्लास बिल्डिंग - जो सॉलिड और विजिबल रूप में होती है, लेकिन मूवेबल नहीं होती है
 * क्लास ट्रैप - जो ठोस रूप में होती है, लेकिन न तो दिखाई देती है और न ही चल सकती है

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

विजिबिलिटी डेलिगेट नामक एक एब्स्ट्रक्ट क्लास का परिचय उपवर्गों के साथ नॉट विजिबल एंड विजिबल के रूप में होता है, जो किसी वस्तु को खींचने का एक साधन प्रदान करता है

class VisibilityDelegate

{ public: virtual void draw = 0; }; class NotVisible : public VisibilityDelegate { public: virtual void draw override { // no-op } }; class Visible : public VisibilityDelegate { public: virtual void draw override { // code to draw a model at the position of this object } }; अपडेट डेलिगेट नामक एक सार वर्ग का परिचय उपवर्गों के साथ मूववेबल और मूववेबल नहीं के रूप में होती है, जो किसी वस्तु को स्थानांतरित करने का साधन प्रदान करती है

class UpdateDelegate

{ public: virtual void update = 0; }; class NotMovable : public UpdateDelegate { public: virtual void update override { // no-op } }; class Movable : public UpdateDelegate { public: virtual void update override { // code to update the position of this object } }; संघट्ट डेलिगेट नामक एक एब्स्ट्रक्ट क्लास का परिचय उपवर्गों ठोस और ठोस नहीं के साथ करते है, जो किसी वस्तु से टकराने का साधन प्रदान करता है class CollisionDelegate

{ public: virtual void collide(Object objects[]) = 0; }; class NotSolid : public CollisionDelegate { public: virtual void collide(Object objects[]) override { // no-op } }; class Solid : public CollisionDelegate { public: virtual void collide(Object objects[]) override { // code to check for and react to collisions with other objects } };

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

अंत में, सदस्यों के साथ ऑब्जेक्ट नामक क्लास का परिचय देते है, यदि इसकी दृश्यता को नियंत्रित करने के लिए एक अद्यतन प्रतिनिधि का उपयोग करके एक दृश्यता प्रतिनिधि की गतिशीलता का उपयोग किया जाता है और संघट्ट प्रतिनिधि का उपयोग करके ठोसता का उपयोग किया जाता है। इस वर्ग में ऐसी विधियाँ होती है, जो इसके सदस्यों को सौंपती हैं। जैसे अपडेट केवल अपडेट डेलिगेट पर एक कॉल विधि का उपयोग करती है class Object

{    VisibilityDelegate* _v; UpdateDelegate* _u; CollisionDelegate* _c; public: Object(VisibilityDelegate* v, UpdateDelegate* u, CollisionDelegate* c)        : _v(v) , _u(u) , _c(c) {}    void update { _u->update; }    void draw { _v->draw; }    void collide(Object objects[]) { _c->collide(objects); } };

तब कंक्रीट इस रूप में दिखती है, class Player : public Object

{ public: Player : Object(new Visible, new Movable, new Solid) {}    // ... }; class Smoke : public Object { public: Smoke : Object(new Visible, new Movable, new NotSolid) {}    // ... };

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

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

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

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

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

उदाहरण के लिए, नीचे दिए गए सी # कोड में, वेरिएबल्स और विधियों के 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."

यह भी देखें

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