मान लीजिए कि आपके पास निम्न स्थिति है
#include <iostream>
class Animal {
public:
virtual void speak() = 0;
};
class Dog : public Animal {
void speak() { std::cout << "woff!" <<std::endl; }
};
class Cat : public Animal {
void speak() { std::cout << "meow!" <<std::endl; }
};
void makeSpeak(Animal &a) {
a.speak();
}
int main() {
Dog d;
Cat c;
makeSpeak(d);
makeSpeak(c);
}
जैसा कि आप देख सकते हैं, मेकस्पीक एक दिनचर्या है जो एक सामान्य पशु वस्तु को स्वीकार करता है। इस मामले में, पशु एक जावा इंटरफ़ेस के समान है, क्योंकि इसमें केवल एक शुद्ध आभासी विधि शामिल है। मेकस्पीक को उस जानवर की प्रकृति का पता नहीं है जो इसे पारित हो जाता है। यह सिर्फ इसे संकेत "बोल" भेजता है और देर से बाध्यकारी को छोड़ देता है कि किस विधि को कॉल करने के लिए ध्यान दें: या तो कैट :: स्पीक () या डॉग :: स्पीक ()। इसका मतलब यह है कि, जहाँ तक मेकस्पीक का सवाल है, वास्तव में जिस उपवर्ग को पारित किया गया है उसका ज्ञान अप्रासंगिक है।
लेकिन अजगर के बारे में क्या? आइए पायथन में उसी मामले के लिए कोड देखें। कृपया ध्यान दें कि मैं एक पल के लिए C ++ केस के समान संभव होने की कोशिश करता हूं:
class Animal(object):
def speak(self):
raise NotImplementedError()
class Dog(Animal):
def speak(self):
print "woff!"
class Cat(Animal):
def speak(self):
print "meow"
def makeSpeak(a):
a.speak()
d=Dog()
c=Cat()
makeSpeak(d)
makeSpeak(c)
अब, इस उदाहरण में आप एक ही रणनीति देखते हैं। आप कुत्तों और बिल्लियों दोनों के जानवरों की श्रेणीबद्ध अवधारणा का लाभ उठाने के लिए विरासत का उपयोग करते हैं। लेकिन पायथन में, इस पदानुक्रम की कोई आवश्यकता नहीं है। यह समान रूप से अच्छी तरह से काम करता है
class Dog:
def speak(self):
print "woff!"
class Cat:
def speak(self):
print "meow"
def makeSpeak(a):
a.speak()
d=Dog()
c=Cat()
makeSpeak(d)
makeSpeak(c)
पाइथन में आप अपनी इच्छानुसार किसी भी वस्तु को संकेत "बोल" भेज सकते हैं। यदि ऑब्जेक्ट इससे निपटने में सक्षम है, तो इसे निष्पादित किया जाएगा, अन्यथा यह एक अपवाद उठाएगा। मान लीजिए कि आप दोनों कोडों के लिए एक क्लास एयरप्लेन जोड़ते हैं, और मेकस्पीक के लिए एरोप्लेन ऑब्जेक्ट सबमिट करते हैं। C ++ के मामले में, यह संकलन नहीं करेगा, क्योंकि हवाई जहाज पशु का एक व्युत्पन्न वर्ग नहीं है। पायथन मामले में, यह रनटाइम पर एक अपवाद को बढ़ाएगा, जो एक अपेक्षित व्यवहार भी हो सकता है।
दूसरी तरफ, मान लीजिए कि आप MouthOfTruth क्लास को मेथड स्पीक () के साथ जोड़ते हैं। C ++ के मामले में, या तो आपको अपनी पदानुक्रम को फिर से भरना होगा, या आपको MouthOfTruth ऑब्जेक्ट्स को स्वीकार करने के लिए एक अलग मेकस्पीक विधि को परिभाषित करना होगा, या जावा में आप व्यवहार को एक कैनपिसफेस में निकाल सकते हैं और प्रत्येक के लिए इंटरफ़ेस लागू कर सकते हैं। कई समाधान हैं ...
मैं जो इंगित करना चाहता हूं वह यह है कि मुझे पायथन (विरासत के अपवादों और अपवादों के पेड़ों के अलावा) में एक भी कारण अभी तक नहीं मिला है, लेकिन मुझे लगता है कि वैकल्पिक रणनीतियां मौजूद हैं। आपको बहुरूपिक प्रदर्शन करने के लिए आधार-व्युत्पन्न पदानुक्रम को लागू करने की आवश्यकता नहीं है। यदि आप कार्यान्वयन को पुन: उपयोग करने के लिए वंशानुक्रम का उपयोग करना चाहते हैं, तो आप इसे उसी लाभ और प्रतिनिधिमंडल के माध्यम से पूरा कर सकते हैं, जोड़ा लाभ के साथ कि आप इसे रनटाइम में बदल सकते हैं, और आप स्पष्ट रूप से निहित के प्रभाव को स्पष्ट रूप से परिभाषित करते हैं, बिना अनपेक्षित दुष्प्रभावों के।
तो, अंत में, सवाल खड़ा होता है: पायथन में विरासत का क्या मतलब है?
संपादित करें : बहुत दिलचस्प जवाब के लिए धन्यवाद। वास्तव में आप इसे कोड पुन: उपयोग के लिए उपयोग कर सकते हैं, लेकिन कार्यान्वयन को पुन: उपयोग करते समय मैं हमेशा सावधान रहता हूं। सामान्य तौर पर, मैं बहुत उथले वंशानुक्रम वाले पेड़ या कोई पेड़ नहीं लगाता, और यदि कोई कार्यक्षमता सामान्य है तो मैं इसे सामान्य मॉड्यूल दिनचर्या के रूप में बताता हूं और फिर प्रत्येक वस्तु से इसे कॉल करता हूं। मुझे परिवर्तन का एक एकल बिंदु होने का लाभ दिखाई देता है (उदाहरण के लिए, डॉग, कैट, मूस और इतने पर जोड़ने के बजाय, मैं सिर्फ पशु को जोड़ता हूं, जो विरासत का मूल लाभ है), लेकिन आप उसी के साथ प्राप्त कर सकते हैं एक प्रतिनिधि श्रृंखला (जैसे। एक ला जावास्क्रिप्ट)। मैं यह दावा नहीं कर रहा हूँ कि यह बेहतर है, बस एक और तरीका है।
मुझे इस संबंध में एक समान पोस्ट भी मिली ।