JavaRush /جاوا بلاگ /Random-UR /مقامی طریقہ کار میں اندرونی کلاسز

مقامی طریقہ کار میں اندرونی کلاسز

گروپ میں شائع ہوا۔
ہیلو! آئیے ایک اور قسم کے نیسٹڈ کلاس کے بارے میں بات کرتے ہیں۔ یعنی، مقامی کلاسوں کے بارے میں (طریقہ مقامی اندرونی کلاسز)۔ مطالعہ کرنے سے پہلے آپ کو سب سے پہلی چیز جو یاد رکھنے کی ضرورت ہے وہ ہے نیسٹڈ کلاسز کی ساخت میں ان کی جگہ۔ مقامی طریقہ میں اندرونی کلاسز - 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 валидации номера
   }
}
اہم!اگر آپ کے پاس جاوا 7 انسٹال ہے تو یہ کوڈ IDEA میں پیسٹ کرنے پر مرتب نہیں ہوگا۔ ہم لیکچر کے آخر میں اس کی وجوہات کے بارے میں بات کریں گے۔ چند الفاظ میں، مقامی کلاسوں کا کام زبان کے ورژن پر بہت زیادہ انحصار کرتا ہے۔ اگر یہ کوڈ آپ کے لیے مرتب نہیں کرتا ہے، تو آپ IDEA میں زبان کے ورژن کو جاوا 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۔ ہم موجودہ صورتحال میں اپنی validator کلاس میں ایسا طریقہ نہیں بنا سکیں گے:
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 میں، ایک مقامی کلاس صرف مقامی متغیر یا میتھڈ پیرامیٹر تک رسائی حاصل کر سکتی ہے اگر انہیں طریقہ کار میں اس طرح قرار دیا گیا ہو 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 متغیرات تک رسائی حاصل ہے۔ جاوا 8 میں، مقامی کلاسوں کا رویہ بدل گیا ہے۔ زبان کے اس ورژن میں، مقامی کلاس کو نہ صرف final-local متغیرات اور پیرامیٹرز تک رسائی حاصل ہے، بلکہ 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 валидации номера
}
لیکن یہ کچھ بھی نہیں ہے کہ مقامی کلاس اندرونی کلاس کا ذیلی قسم ہے! ان کے بھی مشترکہ نکات ہیں۔ ایک مقامی کلاس کو بیرونی طبقے کے تمام (یہاں تک کہ نجی) فیلڈز اور طریقوں تک رسائی حاصل ہے: جامد اور غیر جامد دونوں۔ مثال کے طور پر، آئیے اپنی validator کلاس میں ایک جامد فیلڈ شامل کریں 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;
           }
       }

       //...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