JavaRush /جاوا بلاگ /Random-SD /اندروني ڪلاس مقامي طريقي سان

اندروني ڪلاس مقامي طريقي سان

گروپ ۾ شايع ٿيل
سلام! اچو ته هڪ ٻئي قسم جي nested طبقي جي باري ۾ ڳالهائي. يعني، مقامي طبقن بابت (طريقو مقامي اندروني طبقن). پهرين شيء جيڪا توهان کي پڙهڻ کان پهريان ياد رکڻ جي ضرورت آهي، انهن جي جاء آهي nested طبقن جي جوڙجڪ ۾. اندروني ڪلاس مقامي طريقي ۾ - 2اسان جي ڊراگرام جي بنياد تي، اسان سمجهي سگهون ٿا ته مقامي ڪلاس اندروني طبقن جو هڪ ذيلي قسم آهي، جنهن بابت اسان اڳئين مواد مان هڪ ۾ تفصيل سان ڳالهايو آهي . تنهن هوندي، مقامي طبقن ۾ ڪيترائي اهم خاصيتون آهن ۽ اندروني طبقن کان فرق. انهن جي اعلان ۾ اهم آهي: هڪ مقامي ڪلاس صرف ڪوڊ بلاڪ ۾ اعلان ڪيو ويو آهي. گهڻو ڪري - ٻاهرئين طبقي جي ڪجهه طريقن جي اندر. مثال طور، اهو هن طرح نظر اچي سگهي ٿو:
public class PhoneNumberValidator {

   public void validatePhoneNumber(String number) {

        class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       //...code валидации номера
   }
}
اهم!IDEA ۾ پيسٽ ڪرڻ تي هي ڪوڊ مرتب نه ٿيندو جيڪڏهن توهان وٽ جاوا 7 انسٽال ٿيل آهي، اسان ليڪچر جي آخر ۾ ان جي سببن بابت ڳالهائينداسين. ٿورن لفظن ۾، مقامي طبقن جو ڪم گهڻو ڪري ٻوليء جي نسخي تي منحصر آهي. جيڪڏهن هي ڪوڊ توهان لاءِ گڏ نه ٿو ڪري، ته توهان يا ته IDEA ۾ ٻولي واري ورزن کي Java 8 ۾ تبديل ڪري سگهو ٿا، يا finalميٿڊ پيراميٽر ۾ هڪ لفظ شامل ڪري سگهو ٿا ته جيئن اهو هن طرح نظر اچي: validatePhoneNumber(final String number). ان کان پوء سڀڪنھن شيء کي ڪم ڪندو. هي هڪ ننڍڙو پروگرام آهي - هڪ فون نمبر تصديق ڪندڙ. ان جو طريقو validatePhoneNumber()ان پٽ جي طور تي هڪ اسٽرنگ وٺندو آهي ۽ اهو طئي ڪري ٿو ته ڇا اهو فون نمبر آهي. ۽ هن طريقي جي اندر اسان اسان جي مقامي طبقي جو اعلان ڪيو PhoneNumber. توھان وٽ ھڪڙو منطقي سوال آھي: ڇو؟ هڪ طريقي جي اندر هڪ طبقي جو اعلان ڇو؟ ڇو نه هڪ باقاعده اندروني ڪلاس استعمال ڪريو؟ درحقيقت، هڪ اهو ڪري سگهي ٿو: ڪلاس کي PhoneNumberاندروني ٺاهيو. ٻي شيء اها آهي ته حتمي فيصلو توهان جي پروگرام جي جوڙجڪ ۽ مقصد تي منحصر آهي. اچو ته اندروني طبقن بابت ليڪچر مان اسان جو مثال ياد رکون:
public class Bicycle {

   private String model;
   private int mawWeight;

   public Bicycle(String model, int mawWeight) {
       this.model = model;
       this.mawWeight = mawWeight;
   }

   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!");
       }
   }
}
ان ۾ اسان HandleBar(هينڊ بارز) کي سائيڪل جو اندروني طبقو بڻايو. ڪهڙو فرق آهي؟ سڀ کان پهريان، ڪلاس استعمال ڪرڻ ۾. HandleBarٻئين مثال مان طبقو PhoneNumberپهرين کان وڌيڪ پيچيده ادارو آهي. پهرين، y HandleBarوٽ عوامي طريقا آهن right۽ left(سيٽر ۽ حاصل ڪندڙ نه آهن). ٻيو، اسان اڳ ۾ ئي اڳڪٿي نٿا ڪري سگھون ته Bicycleاسان کي ان جي ۽ ان جي خارجي طبقي جي ڪٿي ضرورت هجي - اهي درجن کان مختلف جايون ۽ طريقا ٿي سگهن ٿا، جيتوڻيڪ ساڳئي پروگرام ۾. پر هڪ طبقي سان PhoneNumberهر شيء بلڪل آسان آهي. اسان جو پروگرام تمام سادو آهي. اهو صرف هڪ فنڪشن آهي - چيڪ ڪرڻ لاء ته ڇا نمبر هڪ فون نمبر آهي. اڪثر صورتن ۾، اسان جو PhoneNumberValidatorهڪ آزاد پروگرام به نه هوندو، پر مکيه پروگرام لاء اختيار جي منطق ۾ صرف هڪ حصو. مثال طور، مختلف ويب سائيٽن تي، جڏهن رجسٽريشن، توهان کي اڪثر چيو ويندو آهي ته هڪ فون نمبر داخل ڪرڻ لاء. ۽ جيڪڏهن توهان نمبرن جي بدران ڪجهه بيوقوف لکندا، سائيٽ هڪ غلطي اڇلائي ويندي: "هي فون نمبر ناهي!" اهڙي سائيٽ جي آپريشن لاء (يا بلڪه، صارف اختيار ڪرڻ واري ميڪانيزم)، ان جي ڊولپرز اسان جي ڪوڊ ۾ هڪ اينالاگ شامل ڪري سگھن ٿا PhoneNumberValidator. ٻين لفظن ۾، اسان وٽ ھڪڙو خارجي طبقو آھي ھڪڙي طريقي سان جيڪو پروگرام ۾ ھڪڙي جڳھ ۾ استعمال ٿيندو ۽ ٻيو ڪٿي. ۽ جيڪڏهن اهو ڪري ٿو، ته پوء ان ۾ ڪجھ به تبديل نه ٿيندو: هڪ طريقو پنهنجو ڪم ڪري ٿو - اهو سڀ ڪجهه آهي. انهي صورت ۾، ڇاڪاڻ ته سڀني ڪم جي منطق کي هڪ طريقي سان گڏ ڪيو ويو آهي، اهو وڌيڪ آسان ۽ صحيح هوندو ته اتي هڪ اضافي طبقي کي گڏ ڪرڻ لاء. ان کي حاصل ڪرڻ ۽ سيٽر کان سواءِ ان جا پنهنجا طريقا نه آهن. اسان کي بنيادي طور تي صرف ان مان تعمير ڪندڙ ڊيٽا جي ضرورت آهي. اهو ٻين طريقن ۾ استعمال نه ڪيو ويو آهي. تنهن ڪري، ان جي باري ۾ معلومات کي وڌائڻ جو ڪو سبب ناهي ته هڪ واحد طريقي کان ٻاهر جتي اهو استعمال ڪيو وڃي. اسان هڪ طريقي سان مقامي طبقي کي اعلان ڪرڻ جو مثال ڏنو، پر اهو واحد امڪان ناهي. اهو صرف هڪ ڪوڊ بلاڪ ۾ اعلان ڪري سگهجي ٿو:
public class PhoneNumberValidator {

   {
       class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

   }

   public void validatePhoneNumber(String phoneNumber) {


       //...code валидации номера
   }
}
يا اڃا به هڪ لوپ ۾ for!
public class PhoneNumberValidator {


   public void validatePhoneNumber(String phoneNumber) {

       for (int i = 0; i < 10; i++) {

           class PhoneNumber {

               private String phoneNumber;

               public PhoneNumber(String phoneNumber) {
                   this.phoneNumber = phoneNumber;
               }
           }

           //...Howая-то логика
       }

       //...code валидации номера
   }
}
پر اهڙا ڪيس انتهائي نادر آهن. اڪثر ڪيسن ۾، اعلان اڃا به طريقي جي اندر ٿيندو. تنهن ڪري، اسان اعلان سان معاملو ڪيو، اسان "فلسفه" بابت پڻ ڳالهايو :) اندروني طبقن کان مقامي طبقن ۾ ٻيون ڪهڙيون خاصيتون ۽ فرق آهن؟ مقامي طبقي جو اعتراض ان طريقي يا بلاڪ کان ٻاهر نه ٿو ٺاهي سگهجي جنهن ۾ اهو اعلان ڪيو ويو آهي. تصور ڪريو اسان کي ھڪڙي طريقي جي ضرورت آھي generatePhoneNumber()جيڪو بي ترتيب فون نمبر ٺاھي ٿو ۽ ھڪڙو واپس ڪري ٿو PhoneNumber. اسان موجوده صورتحال ۾ اسان جي تصديق ڪندڙ ڪلاس ۾ اهڙو طريقو پيدا ڪرڻ جي قابل نه هوندا:
public class PhoneNumberValidator {

   public void validatePhoneNumber(String number) {

        class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       //...code валидации номера
   }

   //ошибка! компилятор не понимает, что это за класс - PhoneNumber
   public PhoneNumber generatePhoneNumber() {

   }

}
مقامي طبقن جي هڪ ٻي اهم خصوصيت مقامي متغير ۽ طريقي جي پيٽرولن تائين رسائي جي صلاحيت آهي. صورت ۾ توهان وساري ڇڏيو، "مقامي" هڪ طريقي سان بيان ڪيل هڪ متغير آهي. اهو آهي، جيڪڏهن اسان پنهنجي مقصدن مان ڪجهه مقصدن لاء String russianCountryCodeهڪ طريقي جي اندر هڪ مقامي متغير ٺاهي سگهون ٿا validatePhoneNumber()، اسان ان کي مقامي طبقي مان رسائي ڪري سگهون ٿا PhoneNumber. تنهن هوندي، هتي ڪيتريون ئي ذيلي ذخيري آهن جيڪي پروگرام ۾ استعمال ٿيل ٻولي جي ورزن تي منحصر آهن. ليڪچر جي شروعات ۾، اسان هڪ نوٽ ڪيو ته هڪ مثال ۾ ڪوڊ جاوا 7 ۾ گڏ نه ٿي سگھي، ياد رکو؟ هاڻي اچو ته ان جي سببن تي نظر وجهون :) جاوا 7 ۾، هڪ لوڪل ڪلاس صرف مقامي variable يا ميٿڊ پيراميٽر تائين رسائي ڪري سگهي ٿو جيڪڏهن اهي طريقي ۾ بيان ڪيا ويا آهن final:
public void validatePhoneNumber(String number) {

   String russianCountryCode = "+7";

   class PhoneNumber {

       private String phoneNumber;

       //ошибка! параметр метода должен быть объявлен How final!
       public PhoneNumber() {
           this.phoneNumber = number;
       }

       public void printRussianCountryCode() {

           //ошибка! локальная переменная должна быть объявлена How final!
           System.out.println(russianCountryCode);
       }

   }

   //...code валидации номера
}
هتي مرتب ڪندڙ ٻه غلطيون اڇلائي ڇڏيو. پر هتي هر شي ترتيب ۾ آهي:
public void validatePhoneNumber(final String number) {

   final String russianCountryCode = "+7";

    class PhoneNumber {

       private String phoneNumber;


       public PhoneNumber() {
           this.phoneNumber = number;
       }

       public void printRussianCountryCode() {

           System.out.println(russianCountryCode);
       }

    }

   //...code валидации номера
}
ھاڻي توھان کي خبر آھي ته ليڪچر جي شروعات ۾ ڪوڊ ڇو مرتب نه ڪيو ويو: جاوا 7 ۾ ھڪڙو مقامي ڪلاس صرف final-method پيرا ميٽرز ۽ final-local variables تائين رسائي آھي. جاوا 8 ۾، مقامي طبقن جو رويو تبديل ٿي چڪو آهي. ٻوليءَ جي هن نسخي ۾، مقامي طبقي کي نه رڳو final-local variables ۽ parameters تائين رسائي آهي، پر effective-final. Effective-finalهڪ متغير آهي جنهن جي قيمت شروعات کان وٺي تبديل نه ڪئي وئي آهي. مثال طور، جاوا 8 ۾ اسان آساني سان ڏيکاري سگهون ٿا هڪ متغير ڪنسول ڏانهن russianCountryCode، جيتوڻيڪ اهو نه آهي final. بنيادي شيء اها آهي ته اهو ان جي معني کي تبديل نٿو ڪري. هن مثال ۾، هر شيء ڪم ڪري ٿو جيئن اهو هجڻ گهرجي:
public void validatePhoneNumber(String number) {

  String russianCountryCode = "+7";

    class PhoneNumber {

       public void printRussianCountryCode() {

           //в Java 7 здесь была бы ошибка
           System.out.println(russianCountryCode);
       }

    }

   //...code валидации номера
}
پر جيڪڏهن اسان شروعاتي ٿيڻ کان فوري طور تي متغير جي قيمت کي تبديل ڪريون ٿا، ڪوڊ مرتب نه ٿيندو.
public void validatePhoneNumber(String number) {

  String russianCountryCode = "+7";
  russianCountryCode = "+8";

    class PhoneNumber {

       public void printRussianCountryCode() {

           //error!
           System.out.println(russianCountryCode);
       }

    }

   //...code валидации номера
}
پر اهو ڪجھ به نه آهي ته مقامي ڪلاس هڪ اندروني طبقي جو هڪ ذيلي قسم آهي! انهن وٽ پڻ عام نقطا آهن. هڪ مقامي طبقي کي ٻاهرين طبقي جي سڀني (جيتوڻيڪ خانگي) شعبن ۽ طريقن تائين رسائي آهي: جامد ۽ غير جامد. مثال طور، اچو ته هڪ جامد فيلڊ شامل ڪريون اسان جي تصديق ڪندڙ طبقي ۾ String phoneNumberRegex:
public class PhoneNumberValidator {

   private static String phoneNumberRegex = "[^0-9]";

   public void validatePhoneNumber(String phoneNumber) {
       class PhoneNumber {

           //......
       }
   }
}
تصديق ڪئي ويندي هن جامد متغير استعمال ڪندي. طريقو چيڪ ڪري ٿو ته ڇا ان ۾ پاس ڪيل اسٽرنگ ۾ اهڙا اکر شامل آهن جيڪي باقاعده اظهار سان نه ٿا ملن " [^0-9]" (يعني اهو ڪردار 0 کان 9 تائين نمبر نه آهي). اسان آساني سان مقامي طبقي مان هن متغير تائين رسائي ڪري سگهون ٿا PhoneNumber. مثال طور، هڪ حاصل ڪندڙ لکو:
public String getPhoneNumberRegex() {

   return phoneNumberRegex;
}
مقامي ڪلاس اندروني طبقن سان ملندڙ جلندڙ آهن ڇو ته اهي ڪنهن به جامد ميمبرن جي وضاحت يا اعلان نٿا ڪري سگهن. جامد طريقن ۾ مقامي طبقن کي صرف بند ٿيل طبقي جي جامد ميمبرن جو حوالو ڏئي سگھن ٿا. مثال طور، جيڪڏهن توهان متغير (فيلڊ) کي ملائيندڙ طبقي جي جامد طور بيان نه ڪيو آهي، جاوا ڪمپلر هڪ غلطي پيدا ڪري ٿو: "هڪ غير جامد متغير هڪ جامد حوالي سان حوالو نٿو ڪري سگهجي." مقامي ڪلاس جامد نه آهن ڇو ته انهن وٽ موجود بلاڪ جي مثالي ميمبرن تائين رسائي آهي. تنهن ڪري، اهي جامد بيانن جي اڪثر قسمن تي مشتمل نٿا ٿي سگهن. توهان بلاڪ جي اندر انٽرفيس جو اعلان نٿا ڪري سگهو؛ Interfaces فطرت ۾ جامد آهن. هي ڪوڊ گڏ نه ڪندو:
public class PhoneNumberValidator {
   public static void validatePhoneNumber(String number) {
       interface I {}

       class PhoneNumber implements I{
           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }
       }

       //...code валидации номера
   }
}
پر جيڪڏهن هڪ انٽرفيس ٻاهرئين طبقي جي اندر اعلان ڪيو ويو آهي، ڪلاس PhoneNumberان کي لاڳو ڪري سگهي ٿو:
public class PhoneNumberValidator {
   interface I {}

   public static void validatePhoneNumber(String number) {

       class PhoneNumber implements I{
           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }
       }

       //...code валидации номера
   }
}
مقامي طبقن جامد شروعات ڪندڙ (شروعاتي بلاڪ) يا انٽرفيس جو اعلان نٿا ڪري سگهن. پر مقامي طبقن ۾ جامد ميمبر ٿي سگهن ٿا، بشرطيڪ اهي مستقل متغير هجن ( static final). اهي ئي آهن، مقامي طبقو! جئين توهان ڏسي سگهو ٿا، اهي اندروني طبقن کان ڪيترائي اختلاف آهن. اسان کي ٻوليءَ جي ورزن جي خاصيتن ۾ به ڌيان ڏيڻو پيو ته اهو سمجھڻ لاءِ ته اهي ڪيئن ڪم ڪن ٿا :) ايندڙ ليڪچر ۾، اسين گمنام اندروني طبقن جي باري ۾ ڳالهائينداسين - نيسٽ ٿيل طبقن جو آخري گروپ. توهان جي پڙهائي سان سٺي قسمت! :)
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION