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

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

گروپ ۾ شايع ٿيل
سلام اچو ته هڪ ٻئي قسم جي 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;
           }
       }

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

   private String model;
   private int maxWeight;

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

   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!");
       }
   }
}
ان ۾، اسان HandleBarسائيڪل جو هڪ اندروني ڪلاس ٺاهيو. ڪهڙو فرق آهي؟ سڀ کان پهريان، ڪلاس جو طريقو مختلف آهي. HandleBarٻئي مثال ۾ ڪلاس پهرين مثال ۾ طبقي کان وڌيڪ پيچيده ادارو آهي PhoneNumber. پهرين، 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) {


       // ...number validation 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;
               }
           }

           // ...some logic
       }

       // ...number validation 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;
           }
       }

       // ...number validation code
   }

   // Error! The compiler does not recognize the PhoneNumber class
   public PhoneNumber generatePhoneNumber() {

   }

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

   String usCountryCode = "+1";

   class PhoneNumber {

       private String phoneNumber;

       // Error! The method parameter must be declared as final!
       public PhoneNumber() {
           this.phoneNumber = number;
       }

       public void printUsCountryCode() {

           // Error! The local variable must be declared as final!
           System.out.println(usCountryCode);
       }

   }

   // ...number validation code
}
هتي مرتب ڪندڙ ٻه غلطيون ٺاهي ٿو. ۽ هتي هر شي ترتيب ۾ آهي:
public void validatePhoneNumber(final String number) {

   final String usCountryCode = "+1";

    class PhoneNumber {

       private String phoneNumber;


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

       public void printUsCountryCode() {

           System.out.println(usCountryCode);
       }

    }

   // ...number validation code
}
هاڻي توهان کي خبر آهي ته سبق جي شروعات کان ڪوڊ ڇو مرتب نه ٿيندو: جاوا 7 ۾، هڪ مقامي طبقي کي صرف finalطريقي جي پيٽرولر ۽ finalمقامي متغير تائين رسائي آهي. جاوا 8 ۾، مقامي طبقن جو رويو تبديل ٿي چڪو آهي. ٻوليءَ جي هن نسخي ۾، هڪ مقامي طبقي کي نه رڳو finalمقامي متغيرن ۽ پيرا ميٽرن تائين پهچ آهي، پر انهن تائين پڻ جيڪي آهن effective-final. Effective-finalهڪ متغير آهي جنهن جي قيمت شروعات کان وٺي تبديل نه ڪئي وئي آهي. مثال طور، جاوا 8 ۾، اسان آساني سان usCountryCodeڪنسول تي متغير ڏيکاري سگهون ٿا، جيتوڻيڪ اهو نه آهي final. اهم شيء اها آهي ته ان جي قيمت تبديل نه ٿيندي آهي. هيٺ ڏنل مثال ۾، هر شي ڪم ڪري ٿي جيئن ان کي گهرجي:
public void validatePhoneNumber(String number) {

  String usCountryCode = "+1";

    class PhoneNumber {

       public void printUsCountryCode() {

           // Java 7 would produce an error here
           System.out.println(usCountryCode);
       }

    }

   // ...number validation code
}
پر جيڪڏهن اسان شروعاتي ٿيڻ کان فوري طور تي متغير جي قيمت کي تبديل ڪريون ٿا، ڪوڊ مرتب نه ٿيندو.
public void validatePhoneNumber(String number) {

  String usCountryCode = "+1";
  usCountryCode = "+8";

    class PhoneNumber {

       public void printUsCountryCode() {

           // Error!
           System.out.println(usCountryCode);
       }

    }

   // ...number validation 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;
}
مقامي ڪلاس اندروني طبقن سان ملندڙ جلندڙ آهن، ڇاڪاڻ ته اهي ڪنهن به جامد ميمبرن جي وضاحت يا اعلان نٿا ڪري سگهن. جامد طريقن ۾ مقامي طبقن کي صرف بند ٿيل طبقي جي جامد ميمبرن جو حوالو ڏئي سگھن ٿا. مثال طور، جيڪڏهن توهان متغير (فيلڊ) کي ملائيندڙ طبقي جي جامد طور بيان نه ڪيو، ته جاوا ڪمپلر هڪ غلطي پيدا ڪري ٿو: "غير جامد متغير کي جامد حوالي سان حوالي نٿو ڪري سگهجي." مقامي طبقو جامد نه آهن، ڇاڪاڻ ته انهن کي انڪولنگ بلاڪ ۾ مثالي ميمبرن تائين رسائي آهي. نتيجي طور، اھي جامد بيانن جي گھڻن قسمن تي مشتمل نٿا ٿي سگھن. توهان بلاڪ جي اندر انٽرفيس جو اعلان نٿا ڪري سگهو: انٽرفيس فطري طور تي جامد آهن. هي ڪوڊ مرتب نٿو ڪري:
public class PhoneNumberValidator {
   public static void validatePhoneNumber(String number) {
       interface I {}

       class PhoneNumber implements I{
           private String phoneNumber;

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

       // ...number validation 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;
           }
       }

       // ...number validation code
   }
}
جامد شروعات ڪندڙ (شروعاتي بلاڪ) يا انٽرفيس کي مقامي طبقن ۾ اعلان نه ٿو ڪري سگھجي. پر مقامي طبقن ۾ جامد ميمبر ٿي سگهن ٿا، بشرطيڪ اهي مستقل متغير هجن ( static final). ۽ هاڻي توهان مقامي طبقن بابت ڄاڻو ٿا، ماڻهو! جئين توهان ڏسي سگهو ٿا، اهي عام اندروني طبقن کان ڪيترائي اختلاف آهن. اسان کي ٻوليءَ جي مخصوص ورزن جي خاصيتن کي به سمجهڻو پوندو ته جيئن اهي ڪيئن ڪم ڪن :) ايندڙ سبق ۾، اسين گمنام اندروني طبقن جي باري ۾ ڳالهائينداسين - نيسٽ ٿيل طبقن جو آخري گروپ. توهان جي پڙهائي ۾ سٺي قسمت! :)
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION