एकाधिक वंशानुक्रम

एकाधिक वंशानुक्रम कुछ ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग भाषा की ऐसी विशेषता है जिसमें ऑब्जेक्ट या क्लास (कंप्यूटर प्रोग्रामिंग) एकल से अधिक पैरेंट ऑब्जेक्ट या सुपरक्लास (कंप्यूटर साइंस) से वंशानुक्रम (वस्तु-उन्मुख प्रोग्रामिंग) कर सकता है। यह एकल वंशानुक्रम से भिन्न है, जहाँ एकल वस्तु या वर्ग केवल एकल विशेष वस्तु या वर्ग से प्राप्त हो सकता है।

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

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

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

कार्यान्वयन
एकाधिक वंशानुक्रम का समर्थन करने वाली भाषाओं में शामिल हैं: C++, सामान्य लिस्प (कॉमन लिस्प ऑब्जेक्ट सिस्टम (CLOS) के माध्यम से), EuLisp (EuLisp ऑब्जेक्ट सिस्टम TELOS के माध्यम से), कर्ल (प्रोग्रामिंग भाषा), डायलन (प्रोग्रामिंग भाषा), एफिल (प्रोग्रामिंग लैंग्वेज), लोगटॉक, ऑब्जेक्ट REXX, स्काला (प्रोग्रामिंग भाषा) (मिक्सिन क्लासेस के उपयोग के माध्यम से), OCaml, पर्ल, POP-11, पायथन (प्रोग्रामिंग लैंग्वेज), R (प्रोग्रामिंग लैंग्वेज), राकू (प्रोग्रामिंग भाषा), और Tcl (बिल्ट-इन) 8.6 से या पिछले संस्करणों में इंक्रीमेंटल Tcl (Incr Tcl) के माध्यम से ).

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

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

PHP विशिष्ट विधि कार्यान्वयनों को इनहेरिट करने के लिए विशेषता वर्गों का उपयोग करती है। रूबी (प्रोग्रामिंग लैंग्वेज) कई तरीकों को इनहेरिट करने के लिए मॉड्यूलर प्रोग्रामिंग का उपयोग करती है।

हीरे की समस्या
हीरे की समस्या (कभी-कभी मौत का घातक हीरा कहा जाता है ) ऐसी अस्पष्टता है जो तब उत्पन्न होती है जब दो वर्ग बी और सी ए से प्राप्त होते हैं, और वर्ग डी बी और सी दोनों से प्राप्त होता है। यदि ए में कोई विधि है कि बी और सी में विधि ओवरराइडिंग (प्रोग्रामिंग) है, और डी इसे ओवरराइड नहीं करता है, तो विधि का कौन सा संस्करण D इनहेरिट करता है: B का, या C का?

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

इस स्थिति में वर्ग वंशानुक्रम आरेख के आकार के कारण इसे हीरे की समस्या कहा जाता है। इस मामले में, कक्षा ए शीर्ष पर है, बी और सी दोनों अलग-अलग इसके नीचे हैं, और डी दोनों को एकल साथ जोड़कर हीरे की आकृति बनाता है।

शमन
बार-बार वंशानुक्रम की इन समस्याओं से निपटने के लिए भाषाओं के अलग-अलग तरीके हैं।

ऐसी भाषाएँ जो केवल एकलल वंशानुक्रम की अनुमति देती हैं, जहाँ एकलल  वर्ग केवल एकल आधार वर्ग से प्राप्त हो सकता है, हीरे की समस्या नहीं है। इसका कारण यह है कि ऐसी भाषाओं में विधियों की पुनरावृत्ति या प्लेसमेंट की परवाह किए बिना वंशानुक्रम श्रृंखला में किसी भी स्तर पर किसी भी विधि का अधिकतम कार्यान्वयन होता है। आमतौर पर ये भाषाएँ कक्षाओं को जावा में इंटरफ़ेस (जावा) कहे जाने वाले कई प्रोटोकॉल (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) को लागू करने की अनुमति देती हैं। ये प्रोटोकॉल विधियों को परिभाषित करते हैं लेकिन ठोस कार्यान्वयन प्रदान नहीं करते हैं। इस रणनीति का उपयोग ActionScript, C Sharp (प्रोग्रामिंग लैंग्वेज) | C#, D (प्रोग्रामिंग लैंग्वेज), Java (प्रोग्रामिंग लैंग्वेज), नेमर्ले, वस्तु पास्कल, उद्देश्य सी, स्मॉलटॉक, स्विफ्ट (प्रोग्रामिंग लैंग्वेज) और PHP (प्रोग्रामिंग लैंग्वेज) द्वारा किया गया है। ). ये सभी भाषाएँ कक्षाओं को कई प्रोटोकॉल लागू करने की अनुमति देती हैं।
 * सी शार्प (प्रोग्रामिंग लैंग्वेज) | सी # (सी # 8.0 के बाद से) डिफ़ॉल्ट इंटरफ़ेस विधि कार्यान्वयन की अनुमति देता है, जिससे एकल वर्ग बनता है, इंटरफेस लागू करना   और   डिफ़ॉल्ट कार्यान्वयन वाले समान तरीकों के साथ, एकल ही हस्ताक्षर के साथ दो इनहेरिट की गई विधियाँ, जिससे हीरे की समस्या होती है। इसे या तो होने से कम किया जाता है   विधि को स्वयं लागू करने के लिए, इसलिए अस्पष्टता को दूर करना, या कॉल करने वाले को पहले कास्ट करने के लिए मजबूर करना   उस विधि के डिफ़ॉल्ट कार्यान्वयन का उपयोग करने के लिए उचित इंटरफ़ेस पर आपत्ति करें (उदा।  ).
 * डिफ़ॉल्ट रूप से C++ प्रत्येक वंशानुक्रम पथ का अलग से अनुसरण करता है, इसलिए a  वस्तु में वास्तव में दो अलग-अलग होंगे   वस्तुओं, और का उपयोग करता है  के सदस्यों को ठीक से योग्य होना चाहिए। यदि से विरासत   को   और से विरासत   को   दोनों चिह्नित हैं (उदाहरण के लिए, ), C++ केवल एकल बनाने के लिए विशेष ध्यान रखता है   वस्तु, और का उपयोग  के सदस्य सही ढंग से काम करते हैं। यदि वर्चुअल इनहेरिटेंस और नॉनवर्चुअल इनहेरिटेंस को मिलाया जाता है, तो एकल ही वर्चुअल होता है , और एकल गैर-आभासी   प्रत्येक गैर-वर्चुअल इनहेरिटेंस पथ के लिए  . C ++ को स्पष्ट रूप से यह बताने की आवश्यकता है कि किस मूल वर्ग का उपयोग किया जाना है, अर्थात।  . सी ++ स्पष्ट दोहराया विरासत का समर्थन नहीं करता है क्योंकि सुपरक्लास का उपयोग करने के लिए अर्हता प्राप्त करने का कोई तरीका नहीं होगा (यानी कक्षा एकल से अधिक बार एकल व्युत्पन्न सूची में दिखाई देती है [वर्ग कुत्ता: सार्वजनिक पशु, पशु])। C++ वर्चुअल इनहेरिटेंस मैकेनिज्म के माध्यम से मल्टीपल क्लास के सिंगल इंस्टेंस को भी बनाने की अनुमति देता है (यानी।   और   उसी वस्तु का संदर्भ देगा)।
 * कॉमन लिस्प कॉमन लिस्प ऑब्जेक्ट सिस्टम उचित डिफ़ॉल्ट व्यवहार और इसे ओवरराइड करने की क्षमता दोनों प्रदान करने का प्रयास करता है। डिफ़ॉल्ट रूप से, इसे सीधे शब्दों में कहें तो विधियों को क्रमबद्ध किया जाता है, जब B को क्लास की परिभाषा में C से पहले लिखा जाता है। सबसे विशिष्ट तर्क वर्गों वाली विधि को चुना गया है (D>(B,C)>A); फिर उस क्रम में जिसमें उपवर्ग परिभाषा (बी> सी) में मूल वर्गों का नाम दिया गया है। हालाँकि, प्रोग्रामर एकल विशिष्ट विधि रिज़ॉल्यूशन ऑर्डर देकर या विधियों के संयोजन के लिए एकल नियम बताकर इसे ओवरराइड कर सकता है। इसे मेथड कॉम्बिनेशन कहा जाता है, जिसे पूरी तरह से नियंत्रित किया जा सकता है। MOP (metaobject प्रोटोकॉल) सिस्टम की स्थिरता को प्रभावित किए बिना इनहेरिटेंस, गतिशील प्रेषण, क्लास इंस्टेंटेशन और अन्य आंतरिक तंत्र को संशोधित करने के साधन भी प्रदान करता है।
 * कर्ल (प्रोग्रामिंग लैंग्वेज) केवल उन वर्गों को अनुमति देता है जिन्हें स्पष्ट रूप से साझा के रूप में चिह्नित किया जाता है ताकि वे बार-बार विरासत में मिलें। साझा कक्षाओं को कक्षा में प्रत्येक नियमित निर्माता (कंप्यूटर विज्ञान) के लिए एकल द्वितीयक निर्माता को परिभाषित करना चाहिए। नियमित कंस्ट्रक्टर को पहली बार कहा जाता है कि साझा वर्ग के लिए राज्य को एकल उपवर्ग निर्माता के माध्यम से आरंभ किया जाता है, और अन्य सभी उपवर्गों के लिए द्वितीयक निर्माता को लागू किया जाएगा।
 * एफिल (प्रोग्रामिंग लैंग्वेज) में, पूर्वजों की विशेषताओं को चुनिंदा और नाम बदलने के निर्देशों के साथ स्पष्ट रूप से चुना जाता है। यह आधार वर्ग की सुविधाओं को उसके वंशजों के बीच साझा करने या उनमें से प्रत्येक को आधार वर्ग की एकल अलग प्रति देने की अनुमति देता है। एफिल पूर्वज वर्गों से विरासत में मिली सुविधाओं को स्पष्ट रूप से जोड़ने या अलग करने की अनुमति देता है। अगर सुविधाओं का नाम और कार्यान्वयन एकल जैसा है, तो एफिल स्वचालित रूप से सुविधाओं में शामिल हो जाएगा। वर्ग लेखक के पास उन्हें अलग करने के लिए विरासत में मिली सुविधाओं का नाम बदलने का विकल्प होता है। एफिल विकास में बहु वंशानुक्रम एकल सामान्य घटना है; डेटा संरचनाओं और एल्गोरिदम की व्यापक रूप से उपयोग की जाने वाली एफिलबेस लाइब्रेरी में अधिकांश प्रभावी कक्षाएं, उदाहरण के लिए, दो या दो से अधिक माता-पिता हैं।
 * जाओ (प्रोग्रामिंग भाषा) संकलन समय पर हीरे की समस्या को रोकता है। अगर एकल संरचना  दो संरचनाओं को एम्बेड करता है   और   जिसमें दोनों का एकल तरीका है , इस प्रकार एकल इंटरफ़ेस को संतुष्ट करता है  , संकलक अस्पष्ट चयनकर्ता के बारे में शिकायत करेगा यदि   कहा जाता है, या यदि का एकल उदाहरण   प्रकार के एकल चर को सौंपा गया है  .   और  के तरीकों को स्पष्ट रूप से कहा जा सकता है   या.
 * जावा (प्रोग्रामिंग भाषा) 8 इंटरफेस पर डिफ़ॉल्ट तरीकों का परिचय देता है। अगर  इंटरफेस हैं,   क्या प्रत्येक एकल सार विधि के लिए एकल अलग कार्यान्वयन प्रदान कर सकता है , हीरे की समस्या पैदा कर रहा है। कोई भी वर्ग   विधि को फिर से लागू करना चाहिए (जिसका शरीर सुपर कार्यान्वयन में से किसी एकल को कॉल अग्रेषित कर सकता है), या अस्पष्टता को संकलन त्रुटि के रूप में खारिज कर दिया जाएगा। जावा 8 से पहले, जावा डायमंड प्रॉब्लम रिस्क के अधीन नहीं था, क्योंकि यह मल्टीपल इनहेरिटेंस का समर्थन नहीं करता था और इंटरफ़ेस डिफ़ॉल्ट तरीके उपलब्ध नहीं थे।
 * वर्जन 1.2 में JavaFX स्क्रिप्ट मिक्सिन्स के उपयोग के माध्यम से मल्टीपल इनहेरिटेंस की अनुमति देता है। विरोध के मामले में, संकलक अस्पष्ट चर या फ़ंक्शन के प्रत्यक्ष उपयोग को प्रतिबंधित करता है। प्रत्येक विरासत में मिले सदस्य को अभी भी वस्तु को ब्याज के मिश्रण में डालकर पहुँचा जा सकता है, उदा।.
 * कोटलिन (प्रोग्रामिंग भाषा) इंटरफ़ेस के कई वंशानुक्रम की अनुमति देता है, हालाँकि, डायमंड प्रॉब्लम परिदृश्य में, चाइल्ड क्लास को उस विधि को ओवरराइड करना चाहिए जो इनहेरिटेंस संघर्ष का कारण बनती है और निर्दिष्ट करती है कि किस पैरेंट क्लास कार्यान्वयन का उपयोग किया जाना चाहिए। उदाहरण के लिए
 * लॉगटॉक इंटरफ़ेस और कार्यान्वयन बहु-विरासत दोनों का समर्थन करता है, विधि उपनामों की घोषणा की अनुमति देता है जो नाम बदलने और उन विधियों तक पहुंच प्रदान करता है जो डिफ़ॉल्ट संघर्ष समाधान तंत्र द्वारा नकाबपोश होंगे।
 * OCaml में, वर्ग परिभाषा के मुख्य भाग में पैरेंट क्लास को अलग-अलग निर्दिष्ट किया जाता है। विधियों (और विशेषताओं) को उसी क्रम में विरासत में मिला है, जिसमें प्रत्येक नई विरासत विधि किसी भी मौजूदा विधियों को ओवरराइड कर रही है। अस्पष्टता के तहत उपयोग करने के लिए किस विधि कार्यान्वयन को हल करने के लिए ओकैमल कक्षा विरासत सूची की अंतिम मिलान परिभाषा चुनता है। डिफ़ॉल्ट व्यवहार को ओवरराइड करने के लिए, वांछित वर्ग परिभाषा के साथ एकल विधि कॉल को योग्यता प्राप्त होती है।
 * पर्ल एकल आदेशित सूची के रूप में इनहेरिट करने के लिए कक्षाओं की सूची का उपयोग करता है। कंपाइलर पहली विधि का उपयोग करता है जो इसे सुपरक्लास सूची की गहराई-पहली खोज या कक्षा पदानुक्रम के सी 3 रैखिकरण का उपयोग करके मिलती है। विभिन्न एकल्सटेंशन वैकल्पिक वर्ग संरचना योजनाएँ प्रदान करते हैं। वंशानुक्रम का क्रम वर्ग शब्दार्थ को प्रभावित करता है। उपरोक्त अस्पष्टता में, class  और उसके पूर्वजों की कक्षा से पहले जाँच की जाएगी   और उसके पूर्वज, इसलिए में विधि   के माध्यम से विरासत में मिलेगा  . इसे Io (प्रोग्रामिंग लैंग्वेज) और Picolisp के साथ शेयर किया जाता है। पर्ल में, इस व्यवहार को का उपयोग करके ओवरराइड किया जा सकता है   या अन्य मॉड्यूल C3 रैखिककरण या अन्य एल्गोरिदम का उपयोग करने के लिए।
 * पायथन (प्रोग्रामिंग लैंग्वेज) में पर्ल के समान संरचना है, लेकिन, पर्ल के विपरीत, इसे भाषा के वाक्य-विन्यास में शामिल करता है। वंशानुक्रम का क्रम वर्ग शब्दार्थ को प्रभावित करता है। पायथन को नई शैली की कक्षाओं की शुरूआत पर इससे निपटना पड़ा, जिनमें से सभी का एकल सामान्य पूर्वज है, . पायथन C3 रैखिककरण (या मेथड रेज़ोल्यूशन ऑर्डर (MRO)) एल्गोरिथम का उपयोग करके कक्षाओं की एकल सूची बनाता है। वह एल्गोरिथ्म दो बाधाओं को लागू करता है: बच्चे अपने माता-पिता से पहले और यदि एकल वर्ग कई वर्गों से विरासत में मिलता है, तो उन्हें आधार वर्गों के टपल में निर्दिष्ट क्रम में रखा जाता है (हालांकि इस मामले में, वंशानुक्रम ग्राफ में उच्च कुछ वर्ग निम्न वर्गों से पहले हो सकते हैं) लेखाचित्र ). इस प्रकार, विधि संकल्प क्रम है: ,  ,  ,.
 * रूबी (प्रोग्रामिंग लैंग्वेज) कक्षाओं में वास्तव में एकल माता-पिता होते हैं, लेकिन कई मॉड्यूल से भी प्राप्त हो सकते हैं; माणिक वर्ग की परिभाषाओं को निष्पादित किया जाता है, और एकल विधि की (पुनः) परिभाषा निष्पादन के समय पहले से मौजूद किसी भी परिभाषा को अस्पष्ट करती है। रनटाइम मेटाप्रोग्रामिंग की अनुपस्थिति में इसमें लगभग वही शब्दार्थ है जो सबसे सही गहराई के पहले रिज़ॉल्यूशन के रूप में है।
 * स्काला (प्रोग्रामिंग लैंग्वेज) लक्षणों के कई तात्कालिकता की अनुमति देता है, जो वर्ग पदानुक्रम और विशेषता पदानुक्रम के बीच अंतर जोड़कर कई वंशानुक्रम की अनुमति देता है। एकलल वर्ग केवल एकलल वर्ग से उत्तराधिकारी हो सकता है, लेकिन वांछित के रूप में कई लक्षणों को मिश्रित कर सकता है। स्कैला परिणामी सूची में प्रत्येक मॉड्यूल की अंतिम घटना को छोड़कर सभी को समाप्त करने से पहले विस्तारित 'लक्षणों' की राइट-फर्स्ट डेप्थ-फर्स्ट सर्च का उपयोग करके विधि नामों को हल करता है। तो, संकल्प आदेश है: [,  ,  ,  ,  ], जो कम हो जाता है [ ,  ,  ,  ]।
 * टीसीएल कई मूल वर्गों की अनुमति देता है; वर्ग घोषणा में विनिर्देशन का क्रम C3 रैखिककरण एल्गोरिथम का उपयोग करने वाले सदस्यों के लिए नाम रिज़ॉल्यूशन को प्रभावित करता है।

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

यह भी देखें

 * निर्देशित ग्राफ
 * निक्सन हीरा

अग्रिम पठन

 * Stroustrup, Bjarne (1999). Multiple Inheritance for C++. Proceedings of the Spring 1987 European Unix Users Group Conference
 * Object-Oriented Software Construction'', Second Edition, by Bertrand Meyer, Prentice Hall, 1997, ISBN 0-13-629155-4

बाहरी संबंध

 * Tutorial on inheritance usage in Eiffel
 * Tutorial on effective use of multiple inheritance in Python
 * An overview of inheritance in Ocaml