मुख्य सामग्री पर जाएं
मॉड्यूल 3 · पाठ 2 का 2पाठ्यक्रम में 6/14~15 min
मॉड्यूल पाठ (2/2)

बहुरूपता और सार वर्ग

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

बहुरूपता

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

Java
class Animal {
    public void makeSound() {
        System.out.println("Verso...");
    }
}

class Dog extends Animal {
    public void makeSound() {
        System.out.println("Woof");
    }
}

class Cat extends Animal {
    public void makeSound() {
        System.out.println("Miao");
    }
}

बहुरूपता के लिए धन्यवाद, हम यह कर सकते हैं:

Java
Animal myAnimal1 = new Dog(); // Polymorphism
Animal myAnimal2 = new Cat(); // Polymorphism

myAnimal1.makeSound(); // Executes Dog's method (Woof)
myAnimal2.makeSound(); // Executes Cat's method (Miao)

किस विधि को लागू करना है इसका निर्णय रनटाइम (लेट बाइंडिंग या डायनेमिक डिस्पैच) पर वास्तविक ऑब्जेक्ट के आधार पर किया जाता है, न कि संदर्भ चर के प्रकार के आधार पर।

सार कक्षाएं (abstract)

एक सार वर्ग abstract कीवर्ड से चिह्नित एक वर्ग है जिसे सीधे त्वरित नहीं किया जा सकता है (आप new MyAbstractClass() नहीं कर सकते हैं)। यह अन्य वर्गों के लिए "आंशिक टेम्पलेट" के रूप में कार्य करता है।

सार विधियाँ

एक अमूर्त वर्ग में अमूर्त विधियाँ शामिल हो सकती हैं: बिना किसी बॉडी (कोई घुंघराले ब्रेसिज़ और कोई कोड नहीं) के साथ घोषित की गई विधियाँ, अर्धविराम के साथ समाप्त होती हैं। सभी विरासत में मिली अमूर्त विधियों को लागू करने के लिए गैर-अमूर्त उपवर्गों की आवश्यकता होती है।

Java
abstract class Shape {
    String color;

    // Abstract method (no body)
    public abstract double getArea();
}

class Circle extends Shape {
    double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    // Required to implement getArea
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

डायनामिक बाइंडिंग / लेट बाइंडिंग

जावा कैसे जानता है कि रनटाइम पर कौन सी विधि निष्पादित करनी है? इस प्रक्रिया को लेट बाइंडिंग (या डायनेमिक बाइंडिंग) के रूप में जाना जाता है। ओवरलोडिंग (जिसे संकलन-समय पर हल किया जाता है) के विपरीत, कंपाइलर को यह नहीं पता होता है कि कौन सी विशिष्ट विधि निष्पादित की जाएगी। इसके बजाय, यह एक सामान्य कॉल निर्देश उत्पन्न करता है। रनटाइम पर, जावा वर्चुअल मशीन (जेवीएम) मेमोरी में वास्तविक ऑब्जेक्ट का निरीक्षण करती है और उस ऑब्जेक्ट के वर्ग में परिभाषित विधि कार्यान्वयन को लागू करती है।

सार कक्षाएं और गुम कार्यान्वयन

यदि कोई उपवर्ग किसी अमूर्त वर्ग से विरासत में मिला है, तो उसके पास दो विकल्प हैं:

  1. सभी अमूर्त तरीकों को लागू करें: इस मामले में, उपवर्ग एक सामान्य (ठोस) वर्ग हो सकता है और इसे तत्काल किया जा सकता है।
  2. स्वयं को सार घोषित करें: यदि उपवर्ग सभी विरासत में मिली अमूर्त विधियों के लिए कार्यान्वयन प्रदान नहीं करता है, तो इसे abstract कीवर्ड के साथ भी घोषित किया जाना चाहिए।
Java
abstract class Animal {
    public abstract void makeSound();
}

// This class MUST be abstract because it does not implement makeSound()
abstract class Canine extends Animal {
    // Inherits makeSound() but does not implement it
}

खुद कोशिश करना

व्यायाम#java.m3.l2.e1
प्रयास: 0लोड हो रहा है...

आकार प्रकार के एक चर की घोषणा करें और बहुरूपता का उपयोग करके उस पर एक नया सर्कल ऑब्जेक्ट निर्दिष्ट करें।

संपादक लोड हो रहा है...
संकेत दिखाएँ

आधार प्रकार को संदर्भ प्रकार के रूप में उपयोग करने के लिए `Shape s = new Circle();` लिखें।

3 प्रयासों के बाद समाधान उपलब्ध है

व्यायाम#java.m3.l2.e2
प्रयास: 0लोड हो रहा है...

शेप क्लास को अमूर्त बनाएं और अमूर्त विधि को डबल getArea() जोड़ें। फिर स्क्वायर को पूरा करें ताकि यह आकार का विस्तार करे और getArea() रिटर्निंग साइड * साइड को लागू करे।

संपादक लोड हो रहा है...
संकेत दिखाएँ

आकार में `सार्वजनिक सार डबल getArea();` घोषित करें। स्क्वायर में, `@ओवरराइड पब्लिक डबल गेटएरिया() { रिटर्न साइड * साइड; जोड़ें; }`.

3 प्रयासों के बाद समाधान उपलब्ध है

व्यायाम#java.m3.l2.e3
प्रयास: 0लोड हो रहा है...

मुख्य विधि में आकार [] प्रकार की एक सरणी घोषित करें जिसमें त्रिज्या 2.0 के साथ एक सर्कल ऑब्जेक्ट और 3.0 पक्ष के साथ एक स्क्वायर ऑब्जेक्ट शामिल है। फिर, getArea() विधि का उपयोग करके प्रत्येक आकृति के क्षेत्र को मुद्रित करने के लिए एक लूप (प्रत्येक के लिए या प्रत्येक के लिए) का उपयोग करें।

संपादक लोड हो रहा है...
संकेत दिखाएँ

`शेप[] शेप्स = { न्यू सर्कल(2.0), न्यू स्क्वायर(3.0) };` के साथ ऐरे को घोषित करें और `फॉर (शेप एस: शेप्स)` प्रिंटिंग `s.getArea()` का उपयोग करके इसके माध्यम से लूप करें।

3 प्रयासों के बाद समाधान उपलब्ध है