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

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

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

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

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

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

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

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

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

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

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

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

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

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