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

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

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

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

इसके अतिरिक्त, Ada, C (प्रोग्रामिंग भाषा), जावा, वस्तु पास्कल, वस्तु-सी (Objective-C), स्विफ्ट एवं पीएचपी (PHP) इंटरफेस के कई उतारधिकार की अनुमति देते हैं (उद्देश्य-सी (Objective-C) एवं स्विफ्ट में प्रोटोकॉल कहा जाता है)। इंटरफेस सार आधार वर्गों के जैसे हैं, जो किसी भी व्यवहार को प्रारम्भ किए बिना, विधि हस्ताक्षर निर्दिष्ट करते हैं। ("शुद्ध" इंटरफेस जैसे जावा में संस्करण 7 तक इंटरफ़ेस में किसी भी कार्यान्वयन या उदाहरण डेटा की अनुमति नहीं देते हैं।) पुनः कई इंटरफेस विधि हस्ताक्षर की घोषणा करते हैं, जैसे ही वह विधि प्रारम्भ होती है (परिभाषित) उतारधिकार श्रृंखला में कहीं भी, यह उस विधि के किसी भी कार्यान्वयन को इसके ऊपर की श्रृंखला में (इसके सुपरक्लास में) ओवरराइड करता है। इसलिए,उतारधिकार श्रृंखला में किसी भी स्तर पर, किसी भी विधि का अधिकतम कार्यान्वयन हो सकता है। इस प्रकार, एकल वंशानुक्रम विधि कार्यान्वयन इंटरफेस के एकाधिक वंशानुक्रम के साथ भी हीरा समस्या को प्रदर्शित नहीं करता है। जावा 8 एवं C# 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