C ++ में एकाधिक वंशानुक्रम क्यों संभव है, लेकिन C # में नहीं?
मुझे लगता है कि (कठिन संदर्भ के बिना), कि जावा में वे भाषा की अभिव्यक्ति को सीमित करना चाहते थे ताकि भाषा सीखने में आसान हो और क्योंकि कई विरासत का उपयोग करने वाला कोड अधिक बार बहुत अधिक जटिल होता है। और क्योंकि फुल मल्टीपल इनहेरिटेंस लागू करने के लिए बहुत अधिक जटिल है, इसलिए इसने वर्चुअल मशीन को बहुत सरल कर दिया (मल्टीपल इनहेरिटेंस विशेष रूप से कचरा कलेक्टर के साथ बहुत बुरी तरह से संपर्क करता है, क्योंकि इसमें पॉइंटर्स को ऑब्जेक्ट के बीच में रखना पड़ता है (बेस की शुरुआत में) )
और जब C # डिजाइन करते हुए मुझे लगता है कि उन्होंने जावा को देखा, तो देखा कि वास्तव में पूर्ण बहु विरासत में बहुत कुछ याद नहीं था और चीजों को सरल रखने के लिए चुना गया था।
C ++ कई बेस कक्षाओं से विरासत में मिली समान विधि हस्ताक्षरों की अस्पष्टता को कैसे हल करता है?
यह नहीं है । विशिष्ट आधार से बेस क्लास पद्धति को कॉल करने के लिए एक सिंटैक्स है, लेकिन केवल एक वर्चुअल विधि को ओवरराइड करने का कोई तरीका नहीं है और यदि आप उपवर्ग में विधि को ओवरराइड नहीं करते हैं, तो आधार को निर्दिष्ट किए बिना इसे कॉल करना संभव नहीं है कक्षा।
और उसी डिज़ाइन को C # में शामिल क्यों नहीं किया गया है?
इसमें शामिल करने के लिए कुछ भी नहीं है।
चूंकि जियोर्जियो ने टिप्पणियों में इंटरफ़ेस एक्सटेंशन विधियों का उल्लेख किया है, इसलिए मैं बताता हूं कि मिक्सिन क्या हैं और उन्हें विभिन्न भाषाओं में कैसे लागू किया जाता है।
जावा और सी # में इंटरफेस केवल घोषणा के तरीकों तक सीमित हैं। लेकिन तरीकों को प्रत्येक वर्ग में लागू करना होगा जो इंटरफ़ेस को विरासत में मिला है। हालांकि इंटरफेस का एक बड़ा वर्ग है, जहां दूसरों के संदर्भ में कुछ तरीकों के डिफ़ॉल्ट कार्यान्वयन प्रदान करना उपयोगी होगा। आम उदाहरण तुलनीय है (छद्म भाषा में):
mixin IComparable {
public bool operator<(IComparable r) = 0;
public bool operator>(IComparable r) { return r < this; }
public bool operator<=(IComparable r) { return !(r < this); }
public bool operator>=(IComparable r) { return !(r > this); }
public bool operator==(IComparable r) { return !(r < this) && !(r > this); }
public bool operator!=(IComparable r) { return r < this || r > this; }
};
पूर्ण वर्ग से अंतर यह है कि इसमें कोई भी डेटा सदस्य नहीं हो सकता है। इसे लागू करने के लिए कई विकल्प हैं। जाहिर है कई विरासत एक है। लेकिन कई विरासत को लागू करने के बजाय जटिल है। लेकिन यह वास्तव में यहाँ की जरूरत नहीं है। इसके बजाय, कई भाषाएं एक इंटरफ़ेस में मिक्सर को विभाजित करके इसे लागू करती हैं, जिसे कक्षा द्वारा लागू किया जाता है और विधि कार्यान्वयन का एक भंडार होता है, जिसे या तो कक्षा में ही इंजेक्ट किया जाता है या एक मध्यवर्ती आधार वर्ग उत्पन्न होता है और उन्हें वहां रखा जाता है। यह रूबी और डी में लागू किया गया है, जावा 8 में लागू किया जाएगा और इसे C ++ में मैन्युअल रूप से पुनरावृत्ति टेम्पलेट पैटर्न का उपयोग करके लागू किया जा सकता है । ऊपर, CRTP फॉर्म में, ऐसा दिखता है:
template <typename Derived>
class IComparable {
const Derived &_d() const { return static_cast<const Derived &>(*this); }
public:
bool operator>(const IComparable &r) const { r._d() < _d(); }
bool operator<=(const IComparable &r) const { !(r._d() < _d(); }
...
};
और जैसे उपयोग किया जाता है:
class Concrete : public IComparable<Concrete> { ... };
यह नियमित आधार वर्ग होगा के रूप में आभासी घोषित किया जा करने के लिए कुछ भी करने की आवश्यकता नहीं है, इसलिए यदि टेम्पलेट में उपयोग किया जाता है उपयोगी अनुकूलन विकल्प खुला छोड़ देता है। ध्यान दें, कि C ++ में यह शायद अभी भी दूसरे माता-पिता के रूप में विरासत में मिला है, लेकिन ऐसी भाषाओं में जो एक से अधिक वंशानुक्रम की अनुमति नहीं देती हैं, यह एकल वंशानुक्रम श्रृंखला में डाली जाती है, इसलिए यह अधिक पसंद है
template <typename Derived, typename Base>
class IComparable : public Base { ... };
class Concrete : public IComparable<Concrete, Base> { ... };
संकलक कार्यान्वयन वर्चुअल प्रेषण से बच सकता है या नहीं भी हो सकता है।
C # में एक अलग कार्यान्वयन चुना गया था। C # में कार्यान्वयन पूरी तरह से अलग वर्ग के स्थिर तरीके हैं और विधि कॉल सिंटैक्स को कंपाइलर द्वारा उचित रूप से व्याख्या किया जाता है यदि दिए गए नाम की एक विधि मौजूद नहीं है, लेकिन एक "विस्तार विधि" परिभाषित है। इसका लाभ यह है कि विस्तार विधियों को पहले से संकलित वर्ग में जोड़ा जा सकता है और नुकसान यह है कि इस तरह के तरीकों को अनुकूलित संस्करण प्रदान करने के लिए उदासीन नहीं किया जा सकता है।