CodeGym /Java Blog /अनियमित /जावा बहुरूपता
John Squirrels
स्तर 41
San Francisco

जावा बहुरूपता

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

जावा में बहुरूपता क्या है?

बहुरूपता वस्तु के विशिष्ट प्रकार के बारे में जानकारी के बिना, समान इंटरफ़ेस वाली वस्तुओं को उसी तरह से व्यवहार करने की प्रोग्राम की क्षमता है। यदि आप बहुरूपता क्या है, इस बारे में किसी प्रश्न का उत्तर देते हैं, तो सबसे अधिक संभावना है कि आपसे यह स्पष्ट करने के लिए कहा जाएगा कि आपका क्या मतलब है। ढेर सारे अतिरिक्त प्रश्नों को ट्रिगर किए बिना, साक्षात्कारकर्ता के लिए एक बार फिर से इसे पूरा करें। साक्षात्कार का समय: जावा में बहुरूपता - 1आप इस तथ्य से शुरू कर सकते हैं कि ओओपी दृष्टिकोण में कक्षाओं पर आधारित वस्तुओं के बीच बातचीत के आधार पर जावा प्रोग्राम बनाना शामिल है। कक्षाएं पहले से लिखे गए ब्लूप्रिंट (टेम्प्लेट) हैं जिनका उपयोग प्रोग्राम में ऑब्जेक्ट बनाने के लिए किया जाता है। इसके अलावा, एक वर्ग में हमेशा एक विशिष्ट प्रकार होता है, जिसमें अच्छी प्रोग्रामिंग शैली के साथ एक नाम होता है जो इसके उद्देश्य का सुझाव देता है। इसके अलावा, यह ध्यान दिया जा सकता है कि चूंकि जावा दृढ़ता से टाइप किया गया है, प्रोग्राम कोड को हमेशा ऑब्जेक्ट प्रकार निर्दिष्ट करना चाहिए जब चर घोषित किए जाते हैं। इस तथ्य को जोड़ें कि सख्त टाइपिंग कोड सुरक्षा और विश्वसनीयता में सुधार करती है, और असंगतता प्रकारों के कारण त्रुटियों को रोकने के लिए संकलन पर भी इसे संभव बनाता है (उदाहरण के लिए, एक स्ट्रिंग को एक संख्या से विभाजित करने का प्रयास करना)। स्वाभाविक रूप से, संकलक को "पता" होना चाहिए घोषित प्रकार - यह JDK का एक वर्ग हो सकता है या जिसे हमने स्वयं बनाया है। साक्षात्कारकर्ता को बताएं कि हमारा कोड न केवल घोषणा में इंगित प्रकार की वस्तुओं का उपयोग कर सकता है, बल्कि इसके वंश का भी उपयोग कर सकता है।यह एक महत्वपूर्ण बिंदु है: हम कई अलग-अलग प्रकारों के साथ एक ही प्रकार के रूप में काम कर सकते हैं (बशर्ते कि ये प्रकार आधार प्रकार से प्राप्त किए गए हों)। इसका अर्थ यह भी है कि यदि हम एक चर घोषित करते हैं जिसका प्रकार एक सुपरक्लास है, तो हम उस चर के वंशजों में से एक का उदाहरण निर्दिष्ट कर सकते हैं। यदि आप एक उदाहरण देंगे तो साक्षात्कारकर्ता इसे पसंद करेंगे। कुछ वर्गों का चयन करें जिन्हें (बेस क्लास के लिए) कई वर्गों द्वारा साझा किया जा सकता है और उनमें से कुछ को इसे प्राप्त कर सकते हैं। बेस क्लास:

public class Dancer {
    private String name;
    private int age;

    public Dancer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void dance() {
        System.out.println(toString() + " I dance like everyone else.");
    }

    @Override
    public String toString() {
        Return "I'm " + name + ". I'm " + age + " years old.";
    }
}
उपवर्गों में, आधार वर्ग की विधि को ओवरराइड करें:

public class ElectricBoogieDancer extends Dancer {
    public ElectricBoogieDancer(String name, int age) {
        super(name, age);
    }
// Override the method of the base class
    @Override
    public void dance() {
        System.out.println(toString () + " I dance the electric boogie!");
    }
}

public class Breakdancer extends Dancer {

    public Breakdancer(String name, int age) {
        super(name, age);
    }
// Override the method of the base class
    @Override
    public void dance() {
        System.out.println(toString() + " I breakdance!");
    }
}
बहुरूपता का एक उदाहरण और एक कार्यक्रम में इन वस्तुओं का उपयोग कैसे किया जा सकता है:

public class Main {

    public static void main(String[] args) {
        Dancer dancer = new Dancer("Fred", 18);

        Dancer breakdancer = new Breakdancer("Jay", 19); // Widening conversion to the base type 
        Dancer electricBoogieDancer = new ElectricBoogieDancer("Marcia", 20); // Widening conversion to the base type

        List<dancer> disco = Arrays.asList(dancer, breakdancer, electricBoogieDancer);
        for (Dancer d : disco) {
            d.dance(); // Call the polymorphic method
        }
    }
}
मुख्य विधि में , दिखाएँ कि lines

Dancer breakdancer = new Breakdancer("Jay", 19);
Dancer electricBoogieDancer = new ElectricBoogieDancer("Marcia", 20);
एक सुपरक्लास का एक चर घोषित करें और इसे एक वस्तु निर्दिष्ट करें जो इसके वंशजों में से एक का उदाहरण है। आपसे सबसे अधिक संभावना पूछी जाएगी कि कंपाइलर असाइनमेंट ऑपरेटर के बाएँ और दाएँ पक्षों पर घोषित प्रकारों की असंगतता पर फ़्लिप क्यों नहीं करता है - आखिरकार, जावा दृढ़ता से टाइप किया गया है। समझाएं कि एक विस्तृत प्रकार का रूपांतरण यहां काम पर है - किसी वस्तु के संदर्भ को उसके आधार वर्ग के संदर्भ के रूप में माना जाता है। क्या अधिक है, कोड में इस तरह के निर्माण का सामना करने के बाद, संकलक स्वचालित रूप से और निहित रूप से रूपांतरण करता है। नमूना कोड दिखाता है कि असाइनमेंट ऑपरेटर ( डांसर ) के बाईं ओर घोषित प्रकार के कई रूप (प्रकार) हैं, जो दाईं ओर घोषित किए गए हैं ( ब्रेकडांसर , इलेक्ट्रिकबूगीडांसर)). सुपरक्लास ( नृत्य पद्धति) में परिभाषित सामान्य कार्यक्षमता के संबंध में प्रत्येक रूप का अपना अनूठा व्यवहार हो सकता है। अर्थात्, एक सुपरक्लास में घोषित विधि को उसके वंशजों में अलग तरीके से लागू किया जा सकता है। इस मामले में, हम मेथड ओवरराइडिंग के साथ काम कर रहे हैं, जो वास्तव में कई रूपों (व्यवहार) का निर्माण करता है। इसे मुख्य विधि में कोड चलाकर देखा जा सकता है: प्रोग्राम आउटपुट: मैं फ्रेड हूं। मैं 18 साल का हूँ। मैं हर किसी की तरह डांस करता हूं। मैं जय हूँ। मेरी उम्र उन्नीस वर्ष है। मैं ब्रेकडांस करता हूं! मैं मार्सिया हूं। मैं 20 साल का हूँ। मैं इलेक्ट्रिक बूगी नृत्य करता हूँ! यदि हम उपवर्गों में विधि को ओवरराइड नहीं करते हैं, तो हमें अलग व्यवहार नहीं मिलेगा। उदाहरण के लिए,ElectricBoogieDancer कक्षाएं, तो कार्यक्रम का आउटपुट यह होगा: मैं फ्रेड हूं। मैं 18 साल का हूँ। मैं हर किसी की तरह डांस करता हूं। मैं जय हूँ। मेरी उम्र उन्नीस वर्ष है। मैं हर किसी की तरह डांस करता हूं। मैं मार्सिया हूं। मैं 20 साल का हूँ। मैं हर किसी की तरह डांस करता हूं। और इसका मतलब यह है कि ब्रेकडांसर और ElectricBoogieDancer कक्षाएं बनाने का कोई मतलब नहीं है । बहुरूपता का सिद्धांत विशेष रूप से कहाँ प्रकट होता है? कार्यक्रम में किसी विशिष्ट प्रकार के ज्ञान के बिना किसी वस्तु का उपयोग कहाँ किया जाता है? हमारे उदाहरण में, ऐसा तब होता है जब डांसर डी ऑब्जेक्ट पर डांस () विधि को कहा जाता है। जावा में, बहुरूपता का अर्थ है कि प्रोग्राम को यह जानने की आवश्यकता नहीं है कि वस्तु a है या नहीं ब्रेकडांसर या इलेक्ट्रिकबूगीडांसर । खास बात यह है कि यह डांसर वर्ग के वंशज हैं। और यदि आप वंशजों का उल्लेख करते हैं, तो आपको ध्यान देना चाहिए कि जावा में वंशानुक्रम न केवल विस्तृत है , बल्कि लागू भी है. अब यह उल्लेख करने का समय है कि जावा एकाधिक वंशानुक्रम का समर्थन नहीं करता है - प्रत्येक प्रकार में एक माता-पिता (सुपरक्लास) और असीमित संख्या में वंशज (उपवर्ग) हो सकते हैं। तदनुसार, कक्षाओं में कार्यों के कई सेट जोड़ने के लिए इंटरफेस का उपयोग किया जाता है। उपवर्गों (विरासत) की तुलना में, माता-पिता वर्ग के साथ इंटरफेस कम युग्मित होते हैं। इनका बहुत व्यापक रूप से उपयोग किया जाता है। जावा में, एक इंटरफ़ेस एक संदर्भ प्रकार है, इसलिए प्रोग्राम इंटरफ़ेस प्रकार का एक चर घोषित कर सकता है। अब उदाहरण देने का समय आ गया है। एक इंटरफ़ेस बनाएँ:

public interface CanSwim {
    void swim();
}
स्पष्टता के लिए, हम विभिन्न असंबद्ध वर्ग लेंगे और उनसे इंटरफ़ेस लागू करेंगे:

public class Human implements CanSwim {
    private String name;
    private int age;

    public Human(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public void swim() {
        System.out.println(toString()+" I swim with an inflated tube.");
    }

    @Override
    public String toString() {
        return "I'm " + name + ". I'm " + age + " years old.";
    }

}
 
public class Fish implements CanSwim {
    private String name;

    public Fish(String name) {
        this.name = name;
    }

    @Override
    public void swim() {
        System.out.println("I'm a fish. My name is " + name + ". I swim by moving my fins.");

    }

public class UBoat implements CanSwim {

    private int speed;

    public UBoat(int speed) {
        this.speed = speed;
    }

    @Override
    public void swim() {
        System.out.println("I'm a submarine that swims through the water by rotating screw propellers. My speed is " + speed + " knots.");
    }
}
मुख्य विधि:

public class Main {

    public static void main(String[] args) {
        CanSwim human = new Human("John", 6);
        CanSwim fish = new Fish("Whale");
        CanSwim boat = new UBoat(25);

        List<swim> swimmers = Arrays.asList(human, fish, boat);
        for (Swim s : swimmers) {
            s.swim();
        }
    }
}
एक इंटरफ़ेस में परिभाषित एक बहुरूपी पद्धति को कॉल करने वाले परिणाम हमें इस इंटरफ़ेस को लागू करने वाले प्रकारों के व्यवहार में अंतर दिखाते हैं। हमारे मामले में, ये तैरने की विधि द्वारा प्रदर्शित विभिन्न तार हैं । हमारे उदाहरण का अध्ययन करने के बाद, साक्षात्कारकर्ता पूछ सकता है कि इस कोड को मुख्य विधि में क्यों चलाना है

for (Swim s : swimmers) {
            s.swim();        
}
हमारे उप-वर्गों में परिभाषित ओवरराइडिंग विधियों को बुलाया जाने का कारण बनता है? कार्यक्रम चलने के दौरान विधि का वांछित कार्यान्वयन कैसे चुना जाता है? इन सवालों का जवाब देने के लिए, आपको लेट (डायनेमिक) बाइंडिंग की व्याख्या करनी होगी। बाइंडिंग का अर्थ है एक विधि कॉल और उसके विशिष्ट वर्ग कार्यान्वयन के बीच एक मानचित्रण स्थापित करना। संक्षेप में, कोड निर्धारित करता है कि कक्षाओं में परिभाषित तीन विधियों में से कौन सा निष्पादित किया जाएगा। जावा डिफ़ॉल्ट रूप से लेट बाइंडिंग का उपयोग करता है, यानी बाइंडिंग रनटाइम पर होती है न कि कंपाइल टाइम पर जैसा कि अर्ली बाइंडिंग के मामले में होता है। इसका मतलब है कि जब कंपाइलर इस कोड को कंपाइल करता है

for (Swim s : swimmers) {
            s.swim();        
}
यह नहीं जानता कि किस वर्ग ( मानव , मछली , या उबोट ) के पास कोड है जो तैरते समय निष्पादित किया जाएगापद्धति कहलाती है। यह तभी निर्धारित होता है जब प्रोग्राम निष्पादित किया जाता है, गतिशील बाध्यकारी तंत्र के लिए धन्यवाद (रनटाइम पर ऑब्जेक्ट के प्रकार की जांच करना और इस प्रकार के लिए सही कार्यान्वयन का चयन करना)। यदि आपसे पूछा जाए कि यह कैसे लागू किया जाता है, तो आप उत्तर दे सकते हैं कि वस्तुओं को लोड और आरंभ करते समय, जेवीएम मेमोरी में टेबल बनाता है और चर को उनके मूल्यों और वस्तुओं को उनके तरीकों से जोड़ता है। ऐसा करने में, यदि कोई वर्ग विरासत में मिला है या इंटरफ़ेस लागू करता है, तो व्यवसाय का पहला क्रम ओवरराइड विधियों की उपस्थिति की जांच करना है। यदि कोई हैं, तो वे इस प्रकार से बंधे हैं। यदि नहीं, तो एक मिलान विधि की खोज उस कक्षा में जाती है जो एक कदम ऊपर है (जनक) और इसी तरह एक बहुस्तरीय पदानुक्रम में रूट तक। जब OOP में बहुरूपता और कोड में इसके कार्यान्वयन की बात आती है, हम ध्यान दें कि आधार वर्गों की अमूर्त परिभाषाएँ प्रदान करने के लिए अमूर्त वर्गों और इंटरफेस का उपयोग करना अच्छा अभ्यास है। यह अभ्यास अमूर्तता के सिद्धांत का अनुसरण करता है - सामान्य व्यवहार और गुणों की पहचान करना और उन्हें एक सार वर्ग में रखना, या केवल सामान्य व्यवहार की पहचान करना और इसे एक इंटरफ़ेस में रखना। बहुरूपता को लागू करने के लिए इंटरफेस और वर्ग विरासत के आधार पर एक वस्तु पदानुक्रम को डिजाइन करना और बनाना आवश्यक है। जावा में बहुरूपता और नवाचारों के संबंध में, हम ध्यान देते हैं कि जावा 8 से शुरू होकर, सार वर्ग और इंटरफेस बनाते समय इसका उपयोग करना संभव है या केवल सामान्य व्यवहार की पहचान करना और उसे एक इंटरफ़ेस में रखना। बहुरूपता को लागू करने के लिए इंटरफेस और वर्ग विरासत के आधार पर एक वस्तु पदानुक्रम को डिजाइन करना और बनाना आवश्यक है। जावा में बहुरूपता और नवाचारों के संबंध में, हम ध्यान देते हैं कि जावा 8 से शुरू होकर, सार वर्ग और इंटरफेस बनाते समय इसका उपयोग करना संभव है या केवल सामान्य व्यवहार की पहचान करना और उसे एक इंटरफ़ेस में रखना। बहुरूपता को लागू करने के लिए इंटरफेस और वर्ग विरासत के आधार पर एक वस्तु पदानुक्रम को डिजाइन करना और बनाना आवश्यक है। जावा में बहुरूपता और नवाचारों के संबंध में, हम ध्यान देते हैं कि जावा 8 से शुरू होकर, सार वर्ग और इंटरफेस बनाते समय इसका उपयोग करना संभव हैबेस क्लास में सार विधियों के लिए डिफ़ॉल्ट कार्यान्वयन लिखने के लिए डिफ़ॉल्ट कीवर्ड। उदाहरण के लिए:

public interface CanSwim {
    default void swim() {
        System.out.println("I just swim");
    }
}
कभी-कभी साक्षात्कारकर्ता पूछते हैं कि बेस क्लास में विधियों को कैसे घोषित किया जाना चाहिए ताकि बहुरूपता के सिद्धांत का उल्लंघन न हो। उत्तर सरल है: ये विधियाँ स्थिर , निजी या अंतिम नहीं होनी चाहिए । निजी केवल एक वर्ग के भीतर एक विधि उपलब्ध कराता है, इसलिए आप इसे उपवर्ग में ओवरराइड नहीं कर पाएंगे। स्टेटिक किसी भी वस्तु के बजाय कक्षा के साथ एक विधि को जोड़ता है, इसलिए सुपरक्लास की विधि को हमेशा बुलाया जाएगा। और final एक विधि को अपरिवर्तनीय और उपवर्गों से छिपा देता है।

बहुरूपता हमें क्या देता है?

आपसे सबसे अधिक संभावना यह भी पूछी जाएगी कि बहुरूपता हमें कैसे लाभ पहुँचाती है। बालों वाले विवरण में उलझे बिना आप इसका उत्तर संक्षेप में दे सकते हैं:
  1. यह वर्ग कार्यान्वयन को बदलना संभव बनाता है। परीक्षण उस पर बनाया गया है।
  2. यह एक्स्टेंसिबिलिटी की सुविधा देता है, जिससे एक नींव बनाना बहुत आसान हो जाता है जिसे भविष्य में बनाया जा सकता है। मौजूदा प्रकार के आधार पर नए प्रकार जोड़ना ओओपी कार्यक्रमों की कार्यक्षमता का विस्तार करने का सबसे आम तरीका है।
  3. यह आपको उन वस्तुओं को संयोजित करने देता है जो एक सामान्य प्रकार या व्यवहार को एक संग्रह या सरणी में साझा करते हैं और उन्हें समान रूप से संभालते हैं (जैसा कि हमारे उदाहरणों में, जहां हमने सभी को नृत्य () या तैरने () के लिए मजबूर किया :)
  4. नए प्रकार बनाने में लचीलापन: आप किसी विधि के माता-पिता के कार्यान्वयन का विकल्प चुन सकते हैं या उपवर्ग में इसे ओवरराइड कर सकते हैं।

कुछ बिदाई शब्द

बहुरूपता एक बहुत ही महत्वपूर्ण और व्यापक विषय है। यह जावा में OOP पर इस लेख के लगभग आधे हिस्से का विषय है और भाषा की नींव का एक अच्छा हिस्सा बनाता है। इंटरव्यू में आप इस सिद्धांत को परिभाषित करने से नहीं बच पाएंगे। यदि आप इसे नहीं जानते हैं या इसे नहीं समझते हैं, तो साक्षात्कार शायद समाप्त हो जाएगा। इसलिए आलसी मत बनो - साक्षात्कार से पहले अपने ज्ञान का आकलन करें और यदि आवश्यक हो तो इसे ताज़ा करें।
टिप्पणियां
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION