CodeGym /Java Blog /अनियमित /नेस्टेड आंतरिक कक्षाएं
John Squirrels
स्तर 41
San Francisco

नेस्टेड आंतरिक कक्षाएं

अनियमित ग्रुप में प्रकाशित
नमस्ते! आज हम एक महत्वपूर्ण विषय पर बात करेंगे - जावा में नेस्टेड क्लासेस कैसे काम करती हैं। जावा आपको दूसरी कक्षा के अंदर कक्षाएं बनाने देता है:

class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
इन आंतरिक वर्गों को नेस्टेड कहा जाता है। वे 2 प्रकारों में विभाजित हैं:
  1. गैर स्थैतिक नेस्टेड कक्षाएं। इन्हें आंतरिक वर्ग भी कहा जाता है।
  2. स्टेटिक नेस्टेड क्लासेस।
बदले में, आंतरिक कक्षाओं में दो अलग-अलग उपश्रेणियाँ होती हैं। एक आंतरिक वर्ग के अलावा केवल एक आंतरिक वर्ग होने के नाते, यह भी हो सकता है:
  • एक स्थानीय वर्ग
  • एक अनाम वर्ग
अस्पष्ट? :) वह ठीक है। यहाँ स्पष्टता के लिए एक आरेख है। यदि आप अचानक स्वयं को भ्रमित पाते हैं तो पाठ के दौरान इस पर वापस आएं! नेस्टेड आंतरिक कक्षाएं - 2आज के पाठ में, हम आंतरिक कक्षाओं (जिन्हें गैर-स्थैतिक नेस्टेड कक्षाओं के रूप में भी जाना जाता है) पर चर्चा करेंगे। उन्हें समग्र आरेख में विशेष रूप से हाइलाइट किया गया है ताकि आप खो न जाएं :) आइए स्पष्ट प्रश्न से शुरू करें: उन्हें "आंतरिक" वर्ग क्यों कहा जाता है? उत्तर बहुत सरल है: क्योंकि वे अन्य वर्गों के अंदर निर्मित होते हैं। यहाँ एक उदाहरण है:

public class Bicycle {

   private String model;
   private int weight;

   public Bicycle(String model, int weight) {
       this.model = model;
       this.weight = weight;
   }
  
   public void start() {
       System.out.println("Let's go!");
   }

   public class Handlebar {

       public void right() {
           System.out.println("Steer right!");
       }

       public void left() {

           System.out.println("Steer left!");
       }
   }

   public class Seat {
      
       public void up() {

           System.out.println("Seat up!");
       }
      
       public void down() {

           System.out.println("Seat down!");
       }
   }
}
यहाँ हमारे पास Bicycleकक्षा है। इसके 2 क्षेत्र और 1 विधि है: start(). नेस्टेड आंतरिक कक्षाएं - 3यह एक साधारण वर्ग से इस मायने में भिन्न है कि इसमें दो वर्ग होते हैं: Handlebarऔर Seat। उनका कोड Bicycleक्लास के अंदर लिखा होता है। ये पूर्ण वर्ग हैं: जैसा कि आप देख सकते हैं, उनमें से प्रत्येक की अपनी विधियाँ हैं। इस बिंदु पर, आपके पास एक प्रश्न हो सकता है: दुनिया में हम एक वर्ग को दूसरे के अंदर क्यों रखेंगे? उन्हें आंतरिक वर्ग क्यों बनाते हैं? ठीक है, मान लीजिए कि हमें अपने कार्यक्रम में हैंडलबार और सीट की अवधारणाओं के लिए अलग-अलग कक्षाओं की आवश्यकता है। बेशक, हमारे लिए उन्हें घोंसला बनाना जरूरी नहीं है! हम सामान्य वर्ग बना सकते हैं। उदाहरण के लिए, इस तरह:

public class Handlebar {
   public void right() {
       System.out.println("Steer right!");
   }

   public void left() {

       System.out.println("Steer left");
   }
}

public class Seat {

   public void up() {

       System.out.println("Seat up!");
   }

   public void down() {

       System.out.println("Seat down!");
   }
}
बहुत अच्छा प्रश्न ! बेशक, हम प्रौद्योगिकी द्वारा सीमित नहीं हैं। ऐसा करना निश्चित रूप से एक विकल्प है। यहां, एक विशिष्ट कार्यक्रम और उसके उद्देश्य के परिप्रेक्ष्य से कक्षाओं का सही डिजाइन अधिक महत्वपूर्ण है। आंतरिक वर्ग एक इकाई को अलग करने के लिए हैं जो किसी अन्य इकाई से अटूट रूप से जुड़ा हुआ है। हैंडलबार, सीट और पैडल एक साइकिल के घटक हैं। साइकिल से अलग होने से उन्हें ज्यादा मतलब नहीं है। यदि हम इन सभी अवधारणाओं को अलग-अलग सार्वजनिक वर्ग बनाते हैं, तो हमारे कार्यक्रम में इस तरह का कोड होता:

public class Main {

   public static void main(String[] args) {
       Handlebar handlebar = new Handlebar();
       handlebar.right();
   }
}
हम्म... इस कोड का अर्थ समझाना और भी मुश्किल है। हमारे पास कुछ अस्पष्ट हैंडलबार हैं (यह क्यों आवश्यक है? ईमानदार होने के लिए कोई विचार नहीं है)। और यह हत्था दाहिनी ओर मुड़ जाता है... बिल्कुल अपने आप, बिना साइकिल के... किसी कारणवश। हैंडलबार की अवधारणा को साइकिल की अवधारणा से अलग करके, हमने अपने कार्यक्रम में कुछ तर्क खो दिए। एक आंतरिक वर्ग का उपयोग करते हुए, कोड बहुत अलग दिखता है:

public class Main {

   public static void main(String[] args) {

       Bicycle peugeot = new Bicycle("Peugeot", 120);
       Bicycle.Handlebar handlebar = peugeot.new Handlebar();
       Bicycle.Seat seat = peugeot.new Seat();

       seat.up();
       peugeot.start();
       handlebar.left();
       handlebar.right();
   }
}
कंसोल आउटपुट:

Seat up! 
Let's go! 
Steer left! 
Steer right!
अब हम जो देखते हैं वह अचानक समझ में आता है! :) हमने एक साइकिल वस्तु बनाई। हमने दो साइकिल "सबऑब्जेक्ट्स" बनाए - एक हैंडलबार और एक सीट। हमने आराम के लिए सीट उठाई और चले गए: आवश्यकतानुसार पेडलिंग और स्टीयरिंग! :) हमें जिन तरीकों की आवश्यकता है उन्हें उपयुक्त वस्तुओं पर बुलाया जाता है। यह सब आसान और सुविधाजनक है। इस उदाहरण में, हैंडलबार और सीट को अलग करना इनकैप्सुलेशन को बढ़ाता है (हम संबंधित वर्ग के अंदर साइकिल के पुर्जों के बारे में डेटा छिपाते हैं) और हमें अधिक विस्तृत सार बनाने की सुविधा देते हैं। अब आइए एक अलग स्थिति देखें। मान लीजिए हम एक ऐसा प्रोग्राम बनाना चाहते हैं जो बाइक की दुकान और बाइक के लिए स्पेयर पार्ट्स का अनुकरण करता है। नेस्टेड आंतरिक कक्षाएं - 4इस स्थिति में, हमारा पिछला समाधान काम नहीं करेगा। बाइक की दुकान पर, साइकिल से अलग होने पर भी साइकिल का प्रत्येक भाग समझ में आता है। उदाहरण के लिए, हमें "ग्राहक को पैडल बेचना", "एक नई सीट खरीदना" आदि विधियों की आवश्यकता होगी। यहां आंतरिक कक्षाओं का उपयोग करना एक गलती होगी - हमारे नए कार्यक्रम में प्रत्येक व्यक्ति साइकिल के हिस्से का अर्थ है जो खड़ा है इसका अपना: इसे साइकिल की अवधारणा से अलग किया जा सकता है। यदि आप सोच रहे हैं कि क्या आपको आंतरिक कक्षाओं का उपयोग करना चाहिए या सभी संस्थाओं को अलग-अलग वर्गों के रूप में व्यवस्थित करना चाहिए, तो आपको ठीक इसी पर ध्यान देने की आवश्यकता है। वस्तु-उन्मुख प्रोग्रामिंग इस मायने में अच्छी है कि यह वास्तविक दुनिया की संस्थाओं को मॉडल करना आसान बनाती है। आंतरिक कक्षाओं का उपयोग करना है या नहीं, यह तय करते समय यह आपका मार्गदर्शक सिद्धांत हो सकता है। एक असली दुकान में, स्पेयर पार्ट्स साइकिल से अलग हैं - यह ठीक है। इसका मतलब यह है कि प्रोग्राम डिजाइन करते समय भी यह ठीक है। ठीक है, हमने "दर्शन" का पता लगा लिया है :) अब आइए आंतरिक कक्षाओं की महत्वपूर्ण "तकनीकी" विशेषताओं से परिचित हों। यहां आपको निश्चित रूप से याद रखने और समझने की आवश्यकता है:
  1. एक आंतरिक वर्ग की वस्तु बाहरी वर्ग की वस्तु के बिना मौजूद नहीं हो सकती।

    Seatयह समझ में आता है: यही कारण है कि हमने अपने कार्यक्रम में और आंतरिक कक्षाएं बनाईं Handlebar- ताकि हम अनाथ हैंडलबार्स और सीटों के साथ समाप्त न हों।

    यह कोड संकलित नहीं होता है:

    
    public static void main(String[] args) {
    
       Handlebar handlebar = new Handlebar();
    }
    

    इससे एक और महत्वपूर्ण विशेषता सामने आती है:

  2. आंतरिक वर्ग की एक वस्तु की बाहरी वर्ग के चरों तक पहुँच होती है।

    उदाहरण के लिए, आइए अपनी कक्षा int seatPostDiameterमें एक चर (सीटपोस्ट के व्यास का प्रतिनिधित्व) जोड़ें।Bicycle

    फिर Seatआंतरिक कक्षा में, हम एक विधि बना सकते हैं displaySeatProperties()जो सीट के गुणों को प्रदर्शित करती है:

    
    public class Bicycle {
    
       private String model;
       private int weight;
    
       private int seatPostDiameter;
    
       public Bicycle(String model, int weight, int seatPostDiameter) {
           this.model = model;
           this.weight = weight;
           this.seatPostDiameter = seatPostDiameter;
    
       }
    
       public void start() {
           System.out.println("Let's go!");
       }
    
       public class Seat {
    
           public void up() {
    
               System.out.println("Seat up!");
           }
    
           public void down() {
    
               System.out.println("Seat down!");
           }
    
           public void displaySeatProperties() {
    
               System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }
    

    और अब हम इस जानकारी को अपने प्रोग्राम में प्रदर्शित कर सकते हैं:

    
    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle bicycle = new Bicycle("Peugeot", 120, 40);
           Bicycle.Seat seat = bicycle.new Seat();
    
           seat.displaySeatProperties();
       }
    }
    

    कंसोल आउटपुट:

    
    Seat properties: seatpost diameter = 40
    

    टिप्पणी:नया वेरिएबल सबसे सख्त एक्सेस मॉडिफायर ( private) के साथ घोषित किया गया है। और अभी भी आंतरिक वर्ग की पहुंच है!

  3. बाहरी वर्ग की स्थिर विधि में आंतरिक वर्ग की वस्तु नहीं बनाई जा सकती है।

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

    लेकिन अगर बाहरी वर्ग की कोई विधि स्थिर है, तो हमारे पास बाहरी वर्ग की कोई वस्तु नहीं हो सकती है! और यह तर्क का उल्लंघन होगा कि एक आंतरिक वर्ग कैसे काम करता है। इस स्थिति में, कंपाइलर एक त्रुटि उत्पन्न करेगा:

    
    public static Seat createSeat() {
      
       // Bicycle.this cannot be referenced from a static context
       return new Seat();
    }
    
  4. एक आंतरिक वर्ग में स्थिर चर और विधियाँ नहीं हो सकती हैं।

    तर्क समान है: स्थैतिक तरीके और चर मौजूद हो सकते हैं और किसी वस्तु की अनुपस्थिति में भी उन्हें बुलाया या संदर्भित किया जा सकता है।

    लेकिन बाहरी वर्ग के किसी वस्तु के बिना, हमारे पास आंतरिक वर्ग तक पहुँच नहीं होगी।

    एक स्पष्ट विरोधाभास! यही कारण है कि आंतरिक कक्षाओं में स्थैतिक चर और विधियों की अनुमति नहीं है।

    यदि आप उन्हें बनाने का प्रयास करते हैं तो संकलक एक त्रुटि उत्पन्न करेगा:

    
    public class Bicycle {
    
       private int weight;
    
    
       public class Seat {
          
           // An inner class cannot have static declarations
           public static void displaySeatProperties() {
    
               System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }
    
  5. आंतरिक वर्ग का ऑब्जेक्ट बनाते समय, इसका एक्सेस संशोधक महत्वपूर्ण होता है।

    एक आंतरिक वर्ग को मानक पहुँच संशोधक के साथ चिह्नित किया जा सकता है: public, private, protected, और package private

    यह क्यों मायने रखता है?

    यह प्रभावित करता है कि हम अपने प्रोग्राम में इनर क्लास के उदाहरण कहाँ बना सकते हैं।

    यदि हमारी Seatकक्षा के रूप में घोषित किया जाता है public, तो हम Seatकिसी अन्य वर्ग में वस्तुएँ बना सकते हैं। केवल आवश्यकता यह है कि बाहरी वर्ग की वस्तु भी मौजूद होनी चाहिए।

    वैसे, हम यहां पहले ही ऐसा कर चुके हैं:

    
    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle peugeot = new Bicycle("Peugeot", 120);
           Bicycle.Handlebar handlebar = peugeot.new Handlebar();
           Bicycle.Seat seat = peugeot.new Seat();
    
           seat.up();
           peugeot.start();
           handlebar.left();
           handlebar.right();
       }
    }
    

    हम आसानी से कक्षा Handlebarसे आंतरिक कक्षा तक पहुँच प्राप्त कर लेते हैं।Main

    यदि हम इनर क्लास को घोषित करते हैं private, तो हम केवल बाहरी क्लास के अंदर ही ऑब्जेक्ट बना पाएंगे।

    Seatहम अब "बाहरी" वस्तु नहीं बना सकते हैं :

    
    private class Seat {
    
       // Methods
    }
    
    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle bicycle = new Bicycle("Peugeot", 120, 40);
    
           // Bicycle.Seat has private access in Bicycle
           Bicycle.Seat seat = bicycle.new Seat();
       }
    }
    

    आप शायद तर्क को पहले ही समझ चुके हैं :)

  6. आंतरिक कक्षाओं के लिए एक्सेस संशोधक सामान्य चर के समान ही काम करते हैं।

    संशोधक protectedएक ही पैकेज में उप-वर्गों और कक्षाओं में एक आवृत्ति चर तक पहुंच प्रदान करता है।

    protectedआंतरिक कक्षाओं के लिए भी काम करता है। हम protectedआंतरिक वर्ग की वस्तुएँ बना सकते हैं:

    • बाहरी वर्ग में;
    • इसके उपवर्गों में;
    • उन कक्षाओं में जो एक ही पैकेज में हैं।

    यदि आंतरिक वर्ग में एक्सेस संशोधक ( package private) नहीं है, तो आंतरिक वर्ग के ऑब्जेक्ट बनाए जा सकते हैं:

    • बाहरी वर्ग में;
    • उन कक्षाओं में जो एक ही पैकेज में हैं।

    आप संशोधक से लंबे समय से परिचित हैं, इसलिए यहां कोई समस्या नहीं है।

अभी के लिए बस इतना ही :) लेकिन सुस्त मत बनो! आंतरिक कक्षाएं काफी व्यापक विषय हैं, जिन्हें हम अगले पाठ में खोजना जारी रखेंगे। अब आप आंतरिक कक्षाओं पर हमारे पाठ्यक्रम के पाठ की अपनी स्मृति को ताज़ा कर सकते हैं । और अगली बार, स्टैटिक नेस्टेड क्लासेस के बारे में बात करते हैं।
टिप्पणियां
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION