क्या कोई सरल उदाहरण प्रदान कर सकता है जो जावा में गतिशील और स्थैतिक बहुरूपता के बीच अंतर बताता है ?
क्या कोई सरल उदाहरण प्रदान कर सकता है जो जावा में गतिशील और स्थैतिक बहुरूपता के बीच अंतर बताता है ?
जवाबों:
बहुरूपता
1. स्टेटिक बाइंडिंग / कम्पाइल-टाइम बाइंडिंग / अर्ली बाइंडिंग / मेथड ओवरलोडिंग। (एक ही क्लास में)
2. डायनेमिक बाइंडिंग / रन-टाइम बाइंडिंग / लेट बाइंडिंग / मेथड ओवरराइडिंग। (विभिन्न वर्गों में)
class Calculation {
void sum(int a,int b){System.out.println(a+b);}
void sum(int a,int b,int c){System.out.println(a+b+c);}
public static void main(String args[]) {
Calculation obj=new Calculation();
obj.sum(10,10,10); // 30
obj.sum(20,20); //40
}
}
class Animal {
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move();//output: Animals can move
b.move();//output:Dogs can walk and run
}
}
Animal reference but Dog object
, हम इसका उपयोग क्यों नहीं कर सकते हैं Dog reference and dog object
?
गतिशील (रन टाइम) बहुरूपता बहुरूपता है जो रन-टाइम पर अस्तित्व में है। यहां, जावा कंपाइलर समझ नहीं पाता है कि किस विधि को संकलन समय पर कहा जाता है। केवल JVM यह तय करता है कि रन-टाइम में किस विधि को कहा जाता है। उदाहरण के तरीकों का उपयोग करके ओवरलोडिंग और विधि ओवरराइडिंग गतिशील बहुरूपता के लिए उदाहरण हैं।
उदाहरण के लिए,
उस एप्लिकेशन पर विचार करें जो विभिन्न प्रकार के दस्तावेजों को क्रमबद्ध और डी-सीरियल करता है।
हमारे पास आधार वर्ग के रूप में 'दस्तावेज़' हो सकते हैं और विभिन्न दस्तावेज़ प्रकार वर्ग इसे प्राप्त कर सकते हैं। जैसे XMLDocument, WordDocument, आदि।
दस्तावेज़ वर्ग 'सीरियलाइज़ ()' और 'डी-सीरीज़ ()' विधियों को आभासी के रूप में परिभाषित करेगा और प्रत्येक व्युत्पन्न वर्ग दस्तावेजों की वास्तविक सामग्री के आधार पर इन तरीकों को अपने तरीके से लागू करेगा।
जब विभिन्न प्रकार के दस्तावेज़ों को क्रमांकित / डी-क्रमांकित किया जाना है, तो दस्तावेज़ ऑब्जेक्ट्स को 'दस्तावेज़' वर्ग संदर्भ (या सूचक) द्वारा संदर्भित किया जाएगा और जब 'सीरियल ()' या 'डी-सीरियलाइज़ ()' विधि कहा जाता है उस पर, आभासी विधियों के उपयुक्त संस्करण कहलाते हैं।
स्टेटिक (संकलन समय) बहुरूपता संकलन समय में प्रदर्शित बहुरूपता है। यहां, जावा कंपाइलर जानता है कि किस विधि को कहा जाता है। स्थैतिक तरीकों का उपयोग करते हुए विधि अधिभार और विधि अधिभावी; निजी या अंतिम विधियों का उपयोग करके ओवरराइड करने की विधि स्थिर बहुरूपता के लिए उदाहरण हैं
उदाहरण के लिए,
एक कर्मचारी वस्तु में दो प्रिंट () तरीके हो सकते हैं जिसमें कोई तर्क नहीं होता है और एक कर्मचारी डेटा के साथ प्रदर्शित होने के लिए एक उपसर्ग स्ट्रिंग लेता है।
इन इंटरफेस को देखते हुए, जब प्रिंट () विधि को बिना किसी तर्क के कॉल किया जाता है, तो कंपाइलर, फ़ंक्शन के तर्कों को देखकर जानता है कि किस फ़ंक्शन को कहा जाना है और यह तदनुसार ऑब्जेक्ट कोड उत्पन्न करता है।
अधिक जानकारी के लिए कृपया "व्हाट इज पोलिमोर्फिज्म" (Google it) पढ़ें।
बाइंडिंग मेथड कॉल और मेथड डेफिनिशन के बीच के लिंक को संदर्भित करता है।
यह तस्वीर स्पष्ट रूप से दिखाती है कि बंधन क्या है।
इस चित्र में, "a1.methodOne ()" कॉल संबंधित मेथडऑन () परिभाषा के लिए बाध्यकारी है और "a1.methodTwo ()" कॉल संबंधित मेथडाउट () परिभाषा के लिए बाध्यकारी है।
प्रत्येक विधि कॉल के लिए उचित विधि परिभाषा होनी चाहिए। यह जावा में एक नियम है। यदि कंपाइलर हर विधि कॉल के लिए उचित विधि परिभाषा नहीं देखता है, तो यह त्रुटि फेंकता है।
अब, स्थैतिक बंधन और जावा में गतिशील बंधन के लिए आते हैं।
जावा में स्थैतिक बंधन:
स्थैतिक बंधन एक बंधन है जो संकलन के दौरान होता है। इसे अर्ली बाइंडिंग भी कहा जाता है क्योंकि बाइंडिंग वास्तव में किसी प्रोग्राम के चलने से पहले होती है
।
नीचे दिए गए चित्र की तरह स्थैतिक बंधन का प्रदर्शन किया जा सकता है।
इस चित्र में, 'ए 1' क्लास ए के ऑब्जेक्ट की ओर इशारा करते हुए टाइप ए का संदर्भ वेरिएबल है।
संकलन के दौरान, बाध्यकारी करते समय, कंपाइलर उस वस्तु के प्रकार की जांच नहीं करता है जिसके लिए एक विशेष संदर्भ चर इंगित कर रहा है। यह केवल संदर्भ चर के प्रकार की जांच करता है, जिसके माध्यम से एक विधि को बुलाया जाता है और जांचता है कि क्या उस प्रकार में इसके लिए कोई विधि परिभाषा मौजूद है।
उदाहरण के लिए, उपरोक्त चित्र में "a1.method ()" विधि कॉल के लिए, कंपाइलर जाँचता है कि क्या क्लास ए में विधि () के लिए मौजूद विधि परिभाषा मौजूद है क्योंकि 'ए 1' क्लास ए प्रकार है। इसी तरह, "a2.method ()" मेथड कॉल के लिए, यह जाँचता है कि क्या क्लास ए में विधि () के लिए मौजूद विधि परिभाषा मौजूद है क्योंकि 'ए 2' भी क्लास ए टाइप है। यह किस वस्तु, 'ए 1' और 'ए 2' की ओर इशारा नहीं करता है। इस प्रकार के बंधन को स्थैतिक बंधन कहा जाता है।
जावा में डायनामिक बाइंडिंग:
डायनेमिक बाइंडिंग एक बाइंडिंग है जो रन टाइम के दौरान होती है। इसे लेट बाइंडिंग भी कहा जाता है क्योंकि बाइंडिंग तब होती है जब प्रोग्राम वास्तव में चल रहा होता है।
रन टाइम के दौरान बाइंडिंग के लिए वास्तविक वस्तुओं का उपयोग किया जाता है। उदाहरण के लिए, उपर्युक्त चित्र में "a1.method ()" कॉल के लिए, वास्तविक ऑब्जेक्ट का तरीका () जो 'ए 1' इंगित कर रहा है, को बुलाया जाएगा। "A2.method ()" कॉल, मेथड () के लिए वास्तविक ऑब्जेक्ट जिस पर 'a2' की ओर इशारा किया जाता है। इस प्रकार के बंधन को डायनेमिक बाइंडिंग कहा जाता है।
उपरोक्त उदाहरण के गतिशील बंधन को नीचे की तरह प्रदर्शित किया जा सकता है।
बहुरूपता: बहुरूपता एक वस्तु की कई रूपों को लेने की क्षमता है। ओओपी में बहुरूपता का सबसे आम उपयोग तब होता है जब एक अभिभावक वर्ग के संदर्भ का उपयोग बाल वर्ग वस्तु के संदर्भ में किया जाता है।
गतिशील बंधन / रनटाइम बहुरूपता:
रन टाइम पॉलिमोर्फिज्म को मेथड ओवरराइडिंग के रूप में भी जाना जाता है। इस तंत्र में जिसके द्वारा रन-टाइम में एक ओवरराइड फ़ंक्शन के लिए कॉल को हल किया जाता है।
public class DynamicBindingTest {
public static void main(String args[]) {
Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
vehicle.start(); //Car's start called because start() is overridden method
}
}
class Vehicle {
public void start() {
System.out.println("Inside start method of Vehicle");
}
}
class Car extends Vehicle {
@Override
public void start() {
System.out.println("Inside start method of Car");
}
}
आउटपुट:
कार का प्रारंभ विधि
स्थैतिक बंधन / संकलन-समय बहुरूपता:
किस विधि को कहा जाना है यह केवल संकलन-समय पर तय किया जाता है।
public class StaticBindingTest {
public static void main(String args[]) {
Collection c = new HashSet();
StaticBindingTest et = new StaticBindingTest();
et.sort(c);
}
//overloaded method takes Collection argument
public Collection sort(Collection c){
System.out.println("Inside Collection sort method");
return c;
}
//another overloaded method which takes HashSet argument which is sub class
public Collection sort(HashSet hs){
System.out.println("Inside HashSet sort method");
return hs;
}
}
आउटपुट: इनसाइड कलेक्शन सॉर्ट मेथो
विधि अधिभार संकलित समय / स्थिर बहुरूपता का एक उदाहरण है क्योंकि विधि कॉल और विधि परिभाषा के बीच बाध्यकारी विधि संकलन समय पर होती है और यह वर्ग के संदर्भ पर निर्भर करती है (संकलन समय पर बनाया गया संदर्भ और ढेर हो जाता है)।
मेथड ओवरराइडिंग रन टाइम / डायनेमिक पॉलीमोर्फिज्म का एक उदाहरण है क्योंकि मेथड कॉल और मेथड डेफिनिशन के बीच मेथड बाइंडिंग रन टाइम पर होता है और यह क्लास के ऑब्जेक्ट (रनटाइम पर बनाई गई वस्तु और हीप पर जाता है) पर निर्भर करता है।
समान्य शब्दों में :
स्थैतिक बहुरूपता : समान विधि का नाम एक ही वर्ग (अलग हस्ताक्षर)में विभिन्न प्रकार या मापदंडों की संख्या के साथ अतिभारित होता है। संकलित समय पर लक्षित विधि कॉल का समाधान किया जाता है।
गतिशील बहुरूपता : समान पद्धति विभिन्न वर्गों में एक ही हस्ताक्षर के साथ ओवरराइड की जाती है । किस विधि पर किस प्रकार का आह्वान किया जा रहा है, यह संकलन समय पर ज्ञात नहीं है, लेकिन रन समय पर तय किया जाएगा।
आमतौर पर ओवरलोडिंग को बहुरूपता नहीं माना जाएगा।
जावा ट्यूटोरियल पेज से :
एक वर्ग के उपवर्ग अपने स्वयं के अनूठे व्यवहार को परिभाषित कर सकते हैं और फिर भी माता-पिता वर्ग की कुछ समान कार्यक्षमता को साझा कर सकते हैं
Generally overloading won't be considered as polymorphism.
क्या आप इस बिंदु पर विस्तार से बता सकते हैं।
Method Overloading को Static Polymorphism के नाम से जाना जाता है और Compile Time Polymorphism के नाम से भी जाना जाता है या Static Binding के क्योंकि Overloaded Method कॉल को कंपाइलर द्वारा लॉजिक लिस्ट और उस रेफरेंस के आधार पर कंपाइल टाइम पर हल किया जाता है, जिस पर हम मेथड कॉल कर रहे हैं।
और मेथड ओवरराइडिंग को गतिशील बहुरूपता या सरल बहुरूपता या रनटाइम विधि डिस्पैच या के रूप में जाना जाता है डायनामिक बाइंडिंग के क्योंकि ओवरराइड मेथड कॉल रनटाइम पर हल हो जाती है।
यह समझने के लिए कि ऐसा क्यों है Mammal
और Human
कक्षा का उदाहरण लें
class Mammal {
public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}
class Human extends Mammal {
@Override
public void speak() { System.out.println("Hello"); }
public void speak(String language) {
if (language.equals("Hindi")) System.out.println("Namaste");
else System.out.println("Hello");
}
}
मैंने आउटपुट को कोड की निचली पंक्तियों में बाइटकोड के साथ शामिल किया है
Mammal anyMammal = new Mammal();
anyMammal.speak(); // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V
human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
और ऊपर दिए गए कोड को देखकर हम देख सकते हैं कि humanMammal.speak (), human.speak () और human.speak ("हिंदी") के बाइटकोड पूरी तरह से अलग हैं क्योंकि कंपाइलर तर्क सूची के आधार पर उनके बीच अंतर करने में सक्षम है। और वर्ग संदर्भ। और यही कारण है कि मेथड ओवरलोडिंग को Static Polymorphism के नाम से जाना जाता है ।
लेकिन anyMammal.speak () और humanMammal.speak () के लिए बाइटकोड समान है क्योंकि कंपाइलर के अनुसार दोनों विधियों को स्तनपायी संदर्भ में कहा जाता है लेकिन दोनों विधि कॉल के लिए आउटपुट अलग-अलग होते हैं क्योंकि रनटाइम JVM में एक संदर्भ और ऑब्जेक्ट जेवीएम कॉल होता है ऑब्जेक्ट पर विधि और यही कारण है कि मेथड ओवरराइडिंग को डायनेमिक पॉलीमोर्फिज़्म के रूप में जाना जाता है।
इसलिए उपरोक्त कोड और बायटेकोड से, यह स्पष्ट है कि संकलन चरण के दौरान कॉलिंग विधि को संदर्भ प्रकार से माना जाता है। लेकिन निष्पादन के समय विधि को उस ऑब्जेक्ट से बुलाया जाएगा जिसे संदर्भ धारण कर रहा है।
यदि आप इसके बारे में अधिक जानना चाहते हैं तो आप JVM हैंडल मेथड ओवरलोडिंग और आंतरिक रूप से ओवरराइडिंग पर अधिक पढ़ सकते हैं ।
स्थैतिक बहुरूपता: वह जगह है जहां निर्णय लेने के लिए किस विधि को हल करना है, संकलन समय के दौरान निर्धारित किया जाता है। मेथड ओवरलोडिंग इसका एक उदाहरण हो सकता है।
डायनामिक पॉलिमोर्फ़िज्म: वह जगह है जहाँ रन-टाइम के दौरान किस विधि को निष्पादित करने का निर्णय लिया जाता है। मेथड ओवरराइडिंग इसका एक उदाहरण हो सकता है।
बहुरूपता एक वस्तु की क्षमता को एक ही ट्रिगर के लिए अलग तरह से व्यवहार करने के लिए संदर्भित करता है।
स्थैतिक बहुरूपता (संकलन-समय बहुरूपता)
गतिशील बहुरूपता (रनटाइम बहुरूपता)
संकलित समय बहुरूपता (स्टेटिक बाइंडिंग / प्रारंभिक बंधन): स्थैतिक बहुरूपता में, यदि हम अपने कोड में एक विधि कहते हैं, तो उस विधि की कौन सी परिभाषा को वास्तव में कहा जाना है, केवल संकलन समय पर हल किया जाता है।
(या)
संकलन के समय, जावा को पता होता है कि विधि हस्ताक्षर की जाँच करके किस विधि को लागू करना है। तो, इसे संकलन-समय बहुरूपता या स्थैतिक बंधन कहा जाता है।
डायनामिक पॉलीमॉर्फिज्म (लेट बाइंडिंग / रनटाइम पॉलिमॉर्फिज्म): रन टाइम के दौरान, जावा यह निर्धारित करने के लिए रनटाइम तक इंतजार करता है कि वास्तव में किस ऑब्जेक्ट को संदर्भ द्वारा इंगित किया जा रहा है। विधि संकल्प को रनटाइम पर लिया गया था, इस कारण से हम रन टाइम पॉलीमॉर्फिज़्म कहते हैं।
नीचे दिए गए कोड पर विचार करें:
public class X
{
public void methodA() // Base class method
{
System.out.println ("hello, I'm methodA of class X");
}
}
public class Y extends X
{
public void methodA() // Derived Class method
{
System.out.println ("hello, I'm methodA of class Y");
}
}
public class Z
{
public static void main (String args []) {
//this takes input from the user during runtime
System.out.println("Enter x or y");
Scanner scanner = new Scanner(System.in);
String value= scanner.nextLine();
X obj1 = null;
if(value.equals("x"))
obj1 = new X(); // Reference and object X
else if(value.equals("y"))
obj2 = new Y(); // X reference but Y object
else
System.out.println("Invalid param value");
obj1.methodA();
}
}
अब, कोड को देखकर आप यह कभी नहीं बता सकते हैं कि मेथड () का कार्यान्वयन किस क्रियान्वयन के लिए किया जाएगा, क्योंकि यह इस बात पर निर्भर करता है कि उपयोगकर्ता रनटाइम के दौरान क्या मूल्य देता है। इसलिए, यह केवल रनटाइम के दौरान तय किया जाता है कि किस विधि को बुलाया जाएगा। इसलिए, रनटाइम बहुरूपता।
विधि अधिभार एक संकलन समय बहुरूपता है, आइए अवधारणा को समझने के लिए एक उदाहरण लेते हैं।
class Person //person.java file
{
public static void main ( String[] args )
{
Eat e = new Eat();
e.eat(noodle); //line 6
}
void eat (Noodles n) //Noodles is a object line 8
{
}
void eat ( Pizza p) //Pizza is a object
{
}
}
इस उदाहरण में, व्यक्ति के पास खाने का एक तरीका है जो दर्शाता है कि वह या तो पिज्जा या नूडल्स खा सकता है। जब हम खाने के लिए इस विधि को ओवरलोडेड करते हैं, तो हम इस संकलक को संकलित करते हैं। कंपाइलर विधि "e.eat (नूडल्स) [जो कि लाइन 6 में है] को हल करता है। लाइन 8 में निर्दिष्ट विधि परिभाषा के साथ यह वह विधि है जो पैरामीटर के रूप में नोडल्स को लेती है। और पूरी प्रक्रिया कंपाइलर द्वारा की जाती है इसलिए यह कंपाइल टाइम पोलीमोर्फिज्म है। विधि परिभाषा के साथ मेथड कॉल के प्रतिस्थापन की प्रक्रिया को बाइंडिंग कहा जाता है, इस मामले में, यह कंपाइलर द्वारा किया जाता है, इसलिए इसे शुरुआती बाइंडिंग कहा जाता है।
नरेश के उत्तर के बाद, वर्चुअल मशीन की उपस्थिति और कोड को मूल रूप से चलने वाले कोड के बजाय रन टाइम पर व्याख्या करने की क्षमता के कारण जावा में गतिशील बहुरूपता केवल 'गतिशील' है।
C ++ में इसे संकलित समय पर हल किया जाना चाहिए यदि इसे gcc का उपयोग करके एक देशी बाइनरी में संकलित किया जा रहा है, जाहिर है; हालांकि, वर्चुअल टेबल में रनटाइम जंप और थंक को अभी भी 'लुकअप' या 'डायनामिक' कहा जाता है। यदि C को B विरासत में मिला है, और आप घोषणा करते हैं , तो c पहले से बाहरी C ऑब्जेक्ट की ओर इशारा करेगा और टेक्स्ट सेगमेंट में C :: method1 () को पॉइंटर पास किया जाएगा। इसका संदर्भ लें: http://www.programmersought.com/article/2572545946/B* b = new C(); b->method1();
, b को C के अंदर B ऑब्जेक्ट को इंगित करने के लिए संकलक द्वारा हल किया जाएगा (एक साधारण वर्ग के लिए एक वर्ग की स्थिति विरासत में मिली, C और C के अंदर B ऑब्जेक्ट एक ही मेमोरी पते पर शुरू होगा तो कुछ भी नहीं किया जाना आवश्यक है; यह उस वीपीआर पर इंगित किया जाएगा जो वे दोनों उपयोग करते हैं)। यदि C को B और A विरासत में मिले, तो Method1 के लिए C एंट्री के अंदर A ऑब्जेक्ट के वर्चुअल फंक्शन टेबल में एक थंक होगा जो पॉइंटर को एन्कैप्सुलेटिंग C ऑब्जेक्ट की शुरुआत में ऑफसेट करेगा और फिर इसे असली A :: method1 () में पास करेगा। पाठ खंड में, जिसे C ने ओवरराइड किया है। के लियेC* c = new C(); c->method1()
जावा में, के लिए B b = new C(); b.method1();
, वर्चुअल मशीन गतिशील रूप से बी के साथ जोड़े गए ऑब्जेक्ट के प्रकार की जांच करने में सक्षम है और सही पॉइंटर पास कर सकती है और सही विधि को कॉल कर सकती है। वर्चुअल मशीन का अतिरिक्त चरण वर्चुअल फ़ंक्शन तालिकाओं की आवश्यकता को समाप्त करता है या संकलन समय पर हल किया जा रहा है, तब भी जब इसे संकलन समय पर जाना जा सकता है। यह ऐसा करने का एक अलग तरीका है जो समझ में आता है जब एक आभासी मशीन शामिल होती है और कोड केवल बायटेकोड पर संकलित किया जाता है।