CodeGym /جاوا بلاگ /Random-SD /اندرين طبقن ۾ داخل ٿيل
John Squirrels
سطح
San Francisco

اندرين طبقن ۾ داخل ٿيل

گروپ ۾ شايع ٿيل
سلام اڄ اسان هڪ اهم موضوع کڻنداسين - ڪيئن nested ڪلاس جاوا ۾ ڪم. جاوا توهان کي ڪنهن ٻئي ڪلاس ۾ ڪلاس ٺاهڻ جي اجازت ڏئي ٿي:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
انهن اندروني طبقن کي nested سڏيو ويندو آهي. اهي 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();
   }
}
هيم... هن ڪوڊ جي معنيٰ بيان ڪرڻ به مشڪل آهي. اسان وٽ ڪجهه مبہم handlebar آهي (ڇو ضروري آهي؟ ڪا خبر ناهي، ايماندار ٿيڻ لاء). ۽ هي هينڊل ساڄي ڦري ٿو... پاڻ ئي، بغير سائيڪل جي... ڪنهن سبب جي ڪري. هينڊل بار جي تصور کي سائيڪل جي تصور کان الڳ ڪرڻ سان، اسان پنهنجي پروگرام ۾ ڪجهه منطق وڃائي ويٺا آهيون. اندروني طبقي کي استعمال ڪندي، ڪوڊ تمام مختلف ڏسڻ ۾ اچي ٿو:
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, and 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