वंशानुक्रम और बहुरूपता के बीच मुख्य अंतर क्या है?


172

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



जवाबों:


289

वंशानुक्रम तब होता है जब एक 'वर्ग' एक मौजूदा 'वर्ग' से निकलता है। इसलिए यदि आपके पास एक Personवर्ग है, तो आपके पास एक ऐसा Studentवर्ग है जो फैली हुई है Person, जो सभी चीजों को Student विरासत में मिलाPerson है। पर्सन में फ़ील्ड्स / मेथड्स में आपके द्वारा उपयोग किए जाने वाले एक्सेस मॉडिफायर के आसपास कुछ विवरण हैं, लेकिन यह मूल विचार है। उदाहरण के लिए, यदि आपके पास एक निजी फ़ील्ड है Person, तो Studentइसे नहीं देखेंगे क्योंकि इसके निजी और निजी फ़ील्ड उप-वर्ग के लिए दृश्यमान नहीं हैं।

पॉलीमॉर्फिज्म यह बताता है कि प्रोग्राम यह कैसे तय करता है कि उसे किन तरीकों का इस्तेमाल करना चाहिए, यह इस बात पर निर्भर करता है कि उसमें किस तरह की चीज है। यदि आपके पास एक है Person, जिसमें एक readविधि है, और आपके पास एक Studentविस्तार है Person, जिसका अपना कार्यान्वयन है read, तो किस विधि को कहा जाता है, यह रनटाइम द्वारा आपके लिए निर्धारित किया जाता है, इस पर निर्भर करता है कि आपके पास एक Personया एक है Student। यह थोड़ा मुश्किल हो जाता है, लेकिन अगर आप कुछ ऐसा करते हैं

Person p = new Student();
p.read();

विद्यार्थी को पढ़ने की विधि कहा जाता है। कार्रवाई में बहुरूपता है। क्योंकि एक आपको लगता है कि काम कर सकते हैं Student एक है Person , लेकिन क्रम स्मार्ट पर्याप्त पता चला है कि के वास्तविक प्रकार है pहै छात्र

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


9
@ hvgtcodes तो संक्षेप में, सुपरक्लास-सबक्लास संबंध वंशानुक्रम है और अभिभावक वर्ग और उसके उप-वर्गों के बीच एक ही तरीके से एक ही तरीके के कार्यान्वयन की अवधारणा है, और उन्हें स्थिति के आधार पर कॉल करते हैं पॉलिमैफ़िज्म,। क्या मैं सही हूँ?
मुहम्मद रायन मुहिम

1
@hvgotcodes लेकिन अगर कहते हैं कि Person's readविधि सार्वजनिक उपयोग संशोधक का उपयोग करके किया जाता है, नहीं होगा Studentवस्तुओं उन्हें पहुंच प्राप्त कर सकेंगे? और फिर Student s = new Student();यह आसान नहीं होगा? मैं वास्तव में अभी भी वास्तव में बहुरूपता के लाभ प्राप्त नहीं करता हूं।
स्कॉर्पियोरिअन

1
@hvgotcodes छात्र s = नया छात्र () काम करेगा। लेकिन मान लीजिए कि आपने इस विचार का उपयोग करते हुए बहुत सारे कोड लिखे, और बाद में आपको एहसास हुआ कि आपने गलती की है। व्यक्ति वास्तव में एक छात्र नहीं है, यह एक शिक्षक है। तो आप बस व्यक्ति p = नए छात्र () से व्यक्तिगत p = नए शिक्षक () में बदल सकते हैं, तो यह आपके जीवन को इतना सरल बना देगा।
मुनमुनब सिप

यहाँ मेरा सवाल यह है कि आप Person p = new Student();इसके बजाय क्यों इस्तेमाल करना चाहेंगे Student p = new Student();?
परफेक्ट कॉन्ट्रैस्ट

@PerfectContrast मुझे लगता है कि यह तब उपयोगी है जब आप छात्र, ड्राइवर, शिक्षक आदि को व्यक्ति के रूप में रखना चाहते हैं और आप उन्हें एक सूची या कुछ के तहत समूहित करते हैं। इसलिए जब आप सभी के लिए 'रीड' कहते हैं, तो हर कोई अपनी 'रीड' विधि कहता है।
सवन्ते

205

एक उपवर्ग में सुपर क्लास की संरचना और व्यवहार का उपयोग करने के लिए विरासत का उल्लेख है ।

बहुरूपता का तात्पर्य उपवर्ग में एक सुपर क्लास के व्यवहार को बदलने से है


5
क्या यह उत्तर स्पष्ट है कि बहुरूपता को वंशानुक्रम की आवश्यकता है?
jaco0646

6
@ jaco0646 - जावा के संदर्भ में, मुझे ऐसा लगता है। (अन्य भाषाओं में, शायद इतना नहीं।) ध्यान दें कि "सुपर क्लास" और "सबक्लास" का उपयोग यहां शिथिल रूप से किया जाता है। बहुरूपता का अर्थ एक इंटरफ़ेस में निर्दिष्ट व्यवहार (लेकिन कार्यान्वित नहीं) की विरासत भी हो सकता है।
टेड हॉप

1
@AlirezaRahmani - मुझे आपकी टिप्पणी समझ में नहीं आती। क्या आपका मतलब है कि विरासत में संपत्ति और व्यवहार दोनों शामिल नहीं हैं? यह जावा (और अधिकांश वर्ग-आधारित, ऑब्जेक्ट-ओरिएंटेड भाषाओं) के उत्तराधिकार को परिभाषित करने के तरीके के विपरीत होगा। से जावा भाषा विशिष्टता, §8.4.8 : "एक वर्ग सी inherits इसके प्रत्यक्ष सुपर क्लास से सभी ठोस तरीकों m(दोनों staticऔर instance) जिसके लिए सुपर क्लास ... की" (विरासत पर विवरण भी)। मेरे लिए "कोड पुन: उपयोग" जैसा लगता है।
टेड हॉप

@ टेडहॉप इनहेरिटेंस मुख्य रूप से एक बहुरूपिक उपकरण है, लेकिन कुछ लोग, उनके बाद के संकट के लिए, इसे पुन: उपयोग / साझा करने के कोड के रूप में उपयोग करने का प्रयास करते हैं। औचित्य "अच्छी तरह से अगर मुझे विरासत में मिला है तो मुझे मुफ्त में सभी तरीके मिलते हैं", लेकिन इस तथ्य को अनदेखा करते हुए कि इन दो वर्गों में संभावित रूप से कोई बहुरूपिक संबंध नहीं है।
अलीरज़ा रहमानी खलीली

1
@AlirezaRahmani - जावा में (जो कि विशेष रूप से टैग के अनुसार ओपी के बारे में पूछा गया है), वर्ग विरासत में सबसे निश्चित रूप से व्यवहार विरासत में शामिल है। यह भाषा की परिभाषा का हिस्सा है। तथ्य यह है कि यह दुरुपयोग किया जा सकता है जैसा कि आप वर्णन करते हैं कि जावा की कमजोरियों में से एक है। (इंटरफेस में परिभाषित स्थिरांक को आयात करने के लिए इंटरफेस को लागू करने के लिए कक्षाएं घोषित करने से संबंधित एक कमजोर कमजोरी। अंत import staticमें इंटरफेस के इस दुरुपयोग को खत्म करने के लिए जावा डिजाइनरों ने पेश किया।) जावा में शुद्ध बहुरूपता के लिए, उपकरण का उपयोग करने के लिए इंटरफेस है, वर्ग विरासत नहीं।
टेड हॉप

63

बहुरूपता : विभिन्न प्रकार की वस्तुओं को एक समान तरीके से व्यवहार करने की क्षमता। उदाहरण: जिराफ़ और मगरमच्छ दोनों जानवर हैं, और जानवर कर सकते हैं Move। यदि आपके पास एक उदाहरण है Animalतो आप Moveबिना जाने या परवाह किए कह सकते हैं कि यह किस प्रकार का जानवर है।

विरासत : यह एक ही समय में बहुरूपता और कोड पुन: उपयोग दोनों को प्राप्त करने का एक तरीका है।

बहुरूपता के अन्य रूप : बहुरूपता को प्राप्त करने के अन्य तरीके हैं, जैसे कि इंटरफेस, जो केवल बहुरूपता प्रदान करते हैं, लेकिन कोई कोड पुन: उपयोग नहीं करता है (कभी-कभी कोड काफी अलग होता है, जैसे कि Moveएक साँप के Moveलिए एक कुत्ते के लिए काफी अलग होगा , इस मामले में एक इंटरफेस इस मामले में बेहतर बहुरूपी विकल्प होगा।

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


17

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

इसके अतिरिक्त, बहुरूपता विधि आह्वान के साथ व्यवहार करता है जबकि वंशानुक्रम डेटा सदस्यों आदि का भी वर्णन करता है।


12

जावा में, दोनों निकट से संबंधित हैं। ऐसा इसलिए है क्योंकि जावा "डायनेमिक प्रेषण" नामक विधि आह्वान के लिए एक तकनीक का उपयोग करता है। अगर मेरे पास

public class A {
  public void draw() { ... }
  public void spin() { ... }
}

public class B extends A {
  public void draw() { ... }
  public void bad() { ... }
}

...

A testObject = new B();

testObject.draw(); // calls B's draw, polymorphic
testObject.spin(); // calls A's spin, inherited by B
testObject.bad(); // compiler error, you are manipulating this as an A

तब हम देखते हैं कि बी spinए से विरासत में मिला है। हालांकि, जब हम ऑब्जेक्ट को हेरफेर करने की कोशिश करते हैं जैसे कि यह एक ए था, तब भी हमें बी के व्यवहार के लिए मिलता है drawdrawव्यवहार बहुरूपी है।

कुछ भाषाओं में, बहुरूपता और वंशानुक्रम काफी निकटता से संबंधित नहीं हैं। C ++ में, उदाहरण के लिए, घोषित किए गए फ़ंक्शंस वर्चुअल इनहेरिट नहीं किए गए हैं, लेकिन गतिशील रूप से नहीं भेजे जाएंगे, इसलिए जब आप इनहेरिटेंस का उपयोग करते हैं, तब भी आपको वह पॉलीमॉर्फिक व्यवहार नहीं मिलेगा।

जावास्क्रिप्ट में, प्रत्येक फ़ंक्शन कॉल गतिशील रूप से भेजा जाता है और आपके पास कमजोर टाइपिंग है। इसका मतलब है कि आपके पास असंबंधित वस्तुओं का एक गुच्छा हो सकता है, प्रत्येक अपने स्वयं के साथ draw, उन पर एक फ़ंक्शन पुनरावृति हो सकता है और फ़ंक्शन को कॉल कर सकता है, और प्रत्येक ठीक व्यवहार करेगा। आपको विरासत की आवश्यकता के बिना अपना स्वयं का बहुरूपिक ड्रॉ करना होगा।


12

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

तो, इसका अर्थ है इनहेरिटेंस का उपयोग करना जो बहुरूपता को प्राप्त करने का एक तरीका है।

बहुरूपता एक वर्ग / इंटरफ़ेस में संभव हो सकता है, लेकिन विरासत हमेशा 2 या अधिक वर्गों / इंटरफेस के बीच होती है। वंशानुक्रम हमेशा "एक" संबंध है, जबकि यह हमेशा बहुरूपता के साथ नहीं होता है (जो दोनों को जोड़ सकता है "-एक" / "संबंध" है।


6

वंशानुक्रम एक स्थिर चीज है (एक वर्ग दूसरे का विस्तार करता है) जबकि बहुरूपता एक गतिशील / रनटाइम चीज है (एक वस्तु अपने गतिशील / रनटाइम प्रकार के अनुसार उसके स्थिर / घोषणा प्रकार के अनुसार व्यवहार करती है)।

उदाहरण के लिए

// This assignment is possible because B extends A
A a = new B();
// polymorphic call/ access
a.foo();

-> हालांकि A का स्थैतिक / घोषणा प्रकार है, वास्तविक गतिशील / रनटाइम प्रकार B है और इस प्रकार a.foo () f को निष्पादित करेगा जैसा कि B में नहीं A में परिभाषित है।


3

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


3

इनहेरिटेंस कोड के पुन: उपयोग से संबंधित एक अवधारणा है। उदाहरण के लिए अगर मैं एक माता पिता के वर्ग कहने Animalऔर यह निश्चित गुण और तरीकों (इस उदाहरण कहते हैं के लिए होता है makeNoise()और sleep()) और मैं बुलाया दो बच्चे कक्षाएं बनाने Dogऔर Cat। चूँकि कुत्ते और बिल्लियाँ दोनों एक ही अंदाज़ में सोते हैं (मुझे लगता है) माता-पिता वर्ग द्वारा प्रदान की जाने वाली और उपवर्गों sleep()में विधि के लिए अधिक कार्यक्षमता जोड़ने की आवश्यकता नहीं है । हालांकि, एक छाल और एक तो हालांकि meowsDogCatAnimalDogCatAnimalकक्षा में शोर करने के लिए एक विधि हो सकती है, एक कुत्ता और एक बिल्ली एक दूसरे और अन्य जानवरों के सापेक्ष अलग-अलग शोर करते हैं। इस प्रकार, उनके विशिष्ट प्रकारों के लिए उस व्यवहार को फिर से परिभाषित करने की आवश्यकता है। इस प्रकार बहुरूपता की परिभाषा। उम्मीद है की यह मदद करेगा।


3

ओरेकल प्रलेखन ने अंतर को ठीक बताया।

विरासत: एक वर्ग अपने सभी सुपरक्लास से खेतों और विधियों को विरासत में लेता है , चाहे वह प्रत्यक्ष या अप्रत्यक्ष हो। एक उपवर्ग उन विधियों को ओवरराइड कर सकता है जो इसे विरासत में मिली हैं, या यह उन क्षेत्रों या विधियों को छिपा सकती हैं जो इसे विरासत में मिली हैं । (ध्यान दें कि खेतों को छिपाना आमतौर पर खराब प्रोग्रामिंग अभ्यास है।)

बहुरूपता: बहुरूपता जीव विज्ञान में एक सिद्धांत को संदर्भित करता है जिसमें एक जीव या प्रजाति के कई अलग-अलग रूप या चरण हो सकते हैं। इस सिद्धांत को ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग और जावा भाषा जैसी भाषाओं पर भी लागू किया जा सकता है। एक वर्ग के उपवर्ग अपने स्वयं के अनूठे व्यवहार को परिभाषित कर सकते हैं और फिर भी माता-पिता वर्ग की कुछ समान कार्यक्षमता को साझा कर सकते हैं।

खेतों के लिए बहुरूपता लागू नहीं है।

संबंधित पोस्ट:

बहुरूपता बनाम ओवरलोडिंग बनाम बहुरूपता


1

बहुरूपता विरासत का एक प्रभाव है । यह केवल उन वर्गों में हो सकता है जो एक दूसरे का विस्तार करते हैं। यह आपको कक्षा के सटीक प्रकार को जाने बिना किसी वर्ग के तरीकों को कॉल करने की अनुमति देता है। इसके अलावा, बहुरूपता रन टाइम पर होता है ।

उदाहरण के लिए, जावा बहुरूपता उदाहरण:

यहां छवि विवरण दर्ज करें

वंशानुक्रम व्युत्पन्न वर्गों को उनके आधार वर्गों के इंटरफेस और कोड साझा करने देता है। यह संकलन के समय होता है ।

उदाहरण के लिए, जावा प्लेटफ़ॉर्म में सभी कक्षाएं ऑब्जेक्ट के वंशज हैं (छवि सौजन्य ओरेकल):

यहां छवि विवरण दर्ज करें

जावा वंशानुक्रम और जावा बहुरूपता के बारे में अधिक जानने के लिए


0

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


0

यदि आप JAVA का उपयोग करते हैं तो यह इस तरह सरल है:

बहुरूपता विरासत में मिली विधियों का उपयोग कर रहा है, लेकिन उन्हें कुछ अलग करने के लिए "ओवरराइडिंग" (या यदि आप सुपर कहते हैं तो तकनीकी रूप से बहुरूपी नहीं होगा)।

यदि मैं गलत हूं तो मुझे सही करों।


0

बहुरूपता का मुख्य उद्देश्य : सुपर क्लास के लिए संदर्भ चर बनाना और उपवर्ग वस्तु धारण करना => एक वस्तु कई व्यवहार कर सकती है

में विरासत , उपवर्ग के गुणों के वारिस सुपर वर्ग


0

वंशानुक्रम बहुरूपता की तरह है, वास्तव में वंशानुक्रम गतिशील बहुरूपता है। इसलिए, जब आप वंशानुक्रम को हटाते हैं तो आप अब और ओवरराइड नहीं कर सकते।


0

इनहेरिटेंस के साथ कार्यान्वयन को सुपरक्लास में परिभाषित किया गया है - इसलिए व्यवहार विरासत में मिला है।

class Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

class Dog extends Animal;

बहुरूपता के साथ कार्यान्वयन को उपवर्ग में परिभाषित किया गया है - इसलिए केवल इंटरफ़ेस विरासत में मिला है।

interface Animal
{
  void move(double newLocation);
}

class Dog implements Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

0

बहुरूपता द्वारा विरासत में प्राप्त किया जाता है Java

├── Animal
└── (instances)
    ├── Cat
    ├── Hamster
    ├── Lion
    └── Moose

├── interface-for-diet
   ├── Carnivore
   └── Herbivore
├── interface-for-habitat
   ├── Pet
   └── Wild

public class Animal {
    void breath() {
    };
}

public interface Carnivore {
    void loveMeat();
}

public interface Herbivore {
    void loveGreens();
}

public interface Pet {
    void liveInside();
}

public interface Wild {
    void liveOutside();
}

public class Hamster extends Animal implements Herbivore, Pet {

    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbor is a Gerbil");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat Carrots, Grapes, Tomatoes, and More");
    }
}

public class Cat extends Animal implements Carnivore, Pet {
    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbr is a Gerbil");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Tuna, Chicken, and More");
    }
}

public class Moose extends Animal implements Herbivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat grass");
    }
}

public class Lion extends Animal implements Carnivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Moose");
    }
}

Hamsterवर्ग से संरचना विरासत में मिलीAnimal , Herbivoreऔर एक घरेलू पालतू जानवर के बहुरूपी व्यवहारवादPet को प्रदर्शित करने के लिए ।

Catवर्ग से संरचना विरासत में मिली है Animal, Carnivoreऔर पॉलीमॉर्फिक व्यवहारवाद काPet प्रदर्शन करने के लिए भी एक घरेलू पालतू जानवर के ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.