JavaRush /جاوا بلاگ /Random-SD /جاوا ۾ داخل ٿيل اندروني ڪلاس يا اندروني ڪلاس

جاوا ۾ داخل ٿيل اندروني ڪلاس يا اندروني ڪلاس

گروپ ۾ شايع ٿيل
سلام! اڄ اسان هڪ اهم موضوع کي ڏسڻ شروع ڪنداسين - جاوا ۾ ڪيئن nested ڪلاس ڪم ڪن ٿا. انگريزيءَ ۾ انهن کي nested classes چوندا آهن. جاوا توهان کي ٻين جي اندر ڪجهه ڪلاس ٺاهڻ جي اجازت ڏئي ٿي:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
اهي طبقا آهن جن کي nested سڏيو ويندو آهي. اهي 2 قسمن ۾ ورهايل آهن:
  1. Non-static nested classes- Non-static nested classes. انهن کي ٻئي طريقي سان اندروني طبقو به سڏيو وڃي ٿو.
  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("Go!");
   }

   public class HandleBar {

       public void right() {
           System.out.println("Steering wheel to the right!");
       }

       public void left() {

           System.out.println("Steering wheel to the left!");
       }
   }

   public class Seat {

       public void up() {

           System.out.println("The seat is up!");
       }

       public void down() {

           System.out.println("The seat is down!");
       }
   }
}
هتي اسان وٽ هڪ ڪلاس آهي Bicycle- سائيڪل. ان ۾ 2 شعبا ۽ 1 طريقو آھي start(). اندريون ڪلاس - 3باقاعده ڪلاس کان ان جو فرق اهو آهي ته ان ۾ ٻه طبقا هوندا آهن، جن جو ڪوڊ اندر لکيل هوندو آهي- Bicycleاهي آهن ڪلاس HandleBar(اسٽيئرنگ ويل) ۽ Seat(سيٽ). اهي مڪمل ڪلاس آهن: جيئن توهان ڏسي سگهو ٿا، انهن مان هر هڪ پنهنجي طريقن سان آهي. هن موقعي تي، توهان وٽ هڪ سوال ٿي سگهي ٿو: اسان هڪ طبقي کي ٻئي ۾ ڇو رکيو؟ ان کي اندروني ڇو بڻايو؟ ٺيڪ، اچو ته اسان کي پروگرام ۾ اسٽيئرنگ ويل ۽ سيٽ لاءِ الڳ ڪلاسن جي ضرورت آهي. پر توهان کي انهن کي گهرائڻ جي ضرورت ناهي! توهان باقاعده ڪلاس ڪري سگهو ٿا. مثال طور، هن طرح:
public class HandleBar {
   public void right() {
       System.out.println("Steering wheel to the right!");
   }

   public void left() {

       System.out.println("Steering wheel left");
   }
}

public class Seat {

   public void up() {

       System.out.println("The seat is up!");
   }

   public void down() {

       System.out.println("The seat is down!");
   }
}
تمام سٺو سوال! يقينا، اسان وٽ ڪا به ٽيڪنيڪل حدون نه آهن - اسان اهو هن طريقي سان ڪري سگهون ٿا. اهو هڪ خاص پروگرام جي نقطي نظر کان ۽ انهي پروگرام جي معنيٰ ۾ ڪلاسن کي صحيح طرح ترتيب ڏيڻ بابت وڌيڪ آهي. اندروني ڪلاس هڪ پروگرام ۾ هڪ خاص اداري کي نمايان ڪرڻ لاءِ ڪلاس آهن جيڪي ڪنهن ٻئي اداري سان جڙيل هوندا آهن. اسٽيرنگ ويل، سيٽ، پيڊل سائيڪل جا حصا آهن. سائيڪل کان الڳ، اهي سمجهه ۾ نه ٿا اچن. جيڪڏھن اسان انھن مڙني طبقن کي الڳ عوامي طبقو بڻايون، ته اسان جو پروگرام ٿي سگھي ٿو، مثال طور، ھيٺ ڏنل ڪوڊ:
public class Main {

   public static void main(String[] args) {
       HandleBar handleBar = new HandleBar();
       handleBar.right();
   }
}
Ummm... هن ڪوڊ جي معنيٰ بيان ڪرڻ به مشڪل آهي. اسان وٽ ڪجهه عجيب سائيڪل جو هينڊ بار آهي (ڇو ضرورت آهي؟ نه ڄاڻ، ايماندار ٿيڻ). ۽ هي اسٽيئرنگ وهيل ساڄي طرف ڦري ٿو... پاڻ ئي، سائيڪل کان سواءِ... ڪنهن سبب جي ڪري. اسٽيرنگ ويل جي جوهر کي سائيڪل جي جوهر کان الڳ ڪرڻ سان، اسان پنهنجي پروگرام جي منطق کي وڃائي ڇڏيو آهي. اندروني طبقي کي استعمال ڪندي، ڪوڊ مڪمل طور تي مختلف نظر اچي ٿو:
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();
   }
}
ڪنسول آئوٽ:

Сиденье поднято выше!
Поехали!
Руль влево!
Руль вправо!
اوچتو ڇا ٿي رهيو هو، احساس ٿيو! :) اسان هڪ سائيڪل اعتراض پيدا ڪيو آهي. اسان ان جا ٻه "سبجڪٽ" ٺاهيا - اسٽيرنگ ويل ۽ سيٽ. اسان سھوليت لاءِ سيٽ کي مٿاھين ڪيو - ۽ اسان ھليا ويا: اسان رول ۽ ھلائي رھيا آھيون جتي اسان کي وڃڻو آھي! :) طريقن کي اسان کي گهربل شيون سڏيو ويندو آهي. هر شي سادي ۽ آسان آهي. هن مثال ۾، هينڊل بار ۽ سيٽ کي نمايان ڪرڻ encapsulation کي وڌايو (اسان سائيڪل جي حصن بابت ڊيٽا کي لاڳاپيل طبقي ۾ لڪائي رهيا آهيون)، ۽ اسان کي وڌيڪ تفصيلي تجزيه ٺاهڻ جي اجازت ڏئي ٿي. هاڻي اچو ته هڪ ٻي صورتحال ڏسو. اچو ته چئو ته اسان هڪ پروگرام ٺاهڻ چاهيون ٿا جيڪو ماڊل سائيڪل ۽ پارٽس اسٽور. اندريون ڪلاس - 4هن صورتحال ۾، اسان جو اڳوڻو حل ناڪام ٿيندو. حصن جي دڪان جي حدن اندر، سائيڪل جي هر انفرادي حصي جو مطلب آهي سائيڪل جي جوهر کان سواءِ. مثال طور، اسان کي طريقن جي ضرورت پوندي جيئن "پيڊل خريد ڪندڙ کي وڪرو ڪريو"، "نئين سيٽ خريد ڪريو"، وغيره. هتي اندروني طبقن کي استعمال ڪرڻ ۾ هڪ غلطي هوندي - اسان جي نئين پروگرام ۾ سائيڪل جي هر انفرادي حصي جي پنهنجي معني آهي: اها سائيڪل جي جوهر کان الڳ آهي، ۽ ڪنهن به طريقي سان ان سان ڳنڍيل ناهي. اھو اھو آھي جيڪو توھان کي ڌيان ڏيڻ گھرجي جيڪڏھن توھان حيران ٿي رھيا آھيو ته ڇا توھان کي اندروني طبقن کي استعمال ڪرڻ جي ضرورت آھي، يا سڀني ادارن کي جدا جدا طبقن ۾ الڳ ڪريو. اعتراض تي مبني پروگرامنگ عظيم آهي ڇاڪاڻ ته اها حقيقي دنيا جي ادارن کي ماڊل ڪرڻ آسان بڻائي ٿي. اھو اھو آھي جيڪو توھان استعمال ڪري سگھوٿا ھدايت جي طور تي جڏھن فيصلو ڪيو وڃي ته ڇا اندروني طبقن کي استعمال ڪرڻ گھرجي. هڪ حقيقي اسٽور ۾، حصا سائيڪل کان الڳ آهن - اهو عام آهي. هن جو مطلب اهو آهي ته اهو صحيح ٿيندو جڏهن هڪ پروگرام ٺاهيندي. ٺيڪ آهي، اسان ”فلسفو“ ترتيب ڏئي ڇڏيو آهي :) هاڻي اچو ته اندروني طبقن جي اهم ”ٽيڪنيڪل“ خصوصيتن کان واقف ٿيون. هتي اهو آهي جيڪو توهان کي ضرور ياد رکڻ ۽ سمجهڻ جي ضرورت آهي:
  1. ”ٻاهرين“ طبقي جي اعتراض کان سواءِ اندروني طبقي جو ڪو به وجود نٿو رهي سگهي.

    اھو منطقي آھي: اھو ئي سبب آھي جو اسان ان کي Seatاندروني HandleBarڪلاس ٺاھيو آھي، انھيءَ لاءِ ته مالڪ کان سواءِ اسٽيئرنگ ويلز ۽ سيٽون اسان جي پروگرام ۾ ھتي ۽ اُتي ظاهر نه ٿين.

    هي ڪوڊ گڏ نه ڪندو:

    public static void main(String[] args) {
    
       HandleBar handleBar = new HandleBar();
    }

    ان مان هيٺيون اهم خصوصيت ملي ٿي:

  2. ھڪڙي اندروني طبقي جي ھڪڙي شيء کي "ٻاهرين" طبقي جي متغيرن تائين رسائي آھي.

    مثال طور، اچو ته اسان جي ڪلاس ۾ Bicycleهڪ متغير شامل ڪريون int seatPostDiameter- سيٽ پوسٽ جو قطر.

    پوءِ اندروني ڪلاس ۾ Seatاسان ھڪڙو طريقو ٺاھي سگھون ٿا getSeatParam()جيڪو اسان کي سيٽ پيٽرولر ٻڌائيندو:

    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("Go!");
       }
    
       public class Seat {
    
           public void up() {
    
               System.out.println("The seat is up!");
           }
    
           public void down() {
    
               System.out.println("The seat is down!");
           }
    
           public void getSeatParam() {
    
               System.out.println("Seat parameter: 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.getSeatParam();
       }
    }

    ڪنسول آئوٽ:

    
    Параметр сиденья: диаметр подседельного штыря = 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 {
    
           //inner class cannot have static declarations
           public static void getSeatParam() {
    
               System.out.println("Seat parameter: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }
  5. جڏهن هڪ اندروني طبقي جو اعتراض ٺاهي، ان جي رسائي موڊفير هڪ اهم ڪردار ادا ڪري ٿو.

    هڪ اندروني ڪلاس کي معياري رسائي جي تبديليءَ سان ظاهر ڪري سگهجي ٿو - public, private, protectedand package private.

    اهو ڇو ضروري آهي؟

    اهو متاثر ڪري ٿو جتي اسان جي پروگرام ۾ اسان اندروني طبقي کي تڪڙو ڪري سگهون ٿا.

    جيڪڏهن اسان جي طبقي کي Seatقرار ڏنو ويو آهي public، اسان ان جي شين کي ڪنهن ٻئي طبقي ۾ ٺاهي سگهون ٿا. ضرورت صرف اها آهي ته ”بيروني“ طبقي جو اعتراض به موجود هجي.

    رستي ۾، اسان اڳ ۾ ئي هتي ڪيو آهي:

    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 a 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