हाय! आज आपण एक महत्त्वाचा विषय घेऊ - नेस्टेड क्लासेस Java मध्ये कसे कार्य करतात. Java तुम्हाला दुसऱ्या वर्गात वर्ग तयार करू देते:

class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
या अंतर्गत वर्गांना नेस्टेड म्हणतात. ते 2 प्रकारांमध्ये विभागलेले आहेत:
  1. नॉन-स्टॅटिक नेस्टेड वर्ग. त्यांना आतील वर्ग असेही म्हणतात.
  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आतील वर्गाच्या वस्तू तयार केल्या जाऊ शकतात:

    • बाह्य वर्गात;
    • समान पॅकेजमधील वर्गांमध्ये.

    आपण बर्याच काळापासून सुधारकांशी परिचित आहात, त्यामुळे येथे कोणतीही समस्या नाही.

सध्या एवढेच आहे :) पण ढिलाई करू नका! अंतर्गत वर्ग हा बर्‍यापैकी विस्तृत विषय आहे जो आम्ही पुढील धड्यात शोधणे सुरू ठेवू. आता तुम्ही आतील वर्गांवरील आमच्या अभ्यासक्रमाच्या धड्याची तुमची आठवण ताजी करू शकता . आणि पुढच्या वेळी, स्टॅटिक नेस्टेड क्लासेसबद्दल बोलूया.