CodeGym /جاوا بلاگ /Random-UR /جنرک میں وائلڈ کارڈز
John Squirrels
سطح
San Francisco

جنرک میں وائلڈ کارڈز

گروپ میں شائع ہوا۔
ہائے! آئیے جنرک کا اپنا مطالعہ جاری رکھیں۔ آپ نے پچھلے اسباق سے ان کے بارے میں کافی علم حاصل کر لیا ہے ( جنرک کے ساتھ کام کرتے وقت ورارگس کے استعمال کے بارے میں اور ٹائپ ایریزر کے بارے میں )، لیکن ایک اہم موضوع ہے جس پر ہم نے ابھی تک غور نہیں کیا ہے — وائلڈ کارڈز ۔ یہ جنرک کی بہت اہم خصوصیت ہے۔ اتنا کہ ہم نے اس کے لیے ایک الگ سبق وقف کر دیا ہے! اس نے کہا، وائلڈ کارڈز کے بارے میں کوئی خاص پیچیدہ بات نہیں ہے۔ آپ اسے فوراً دیکھ لیں گے :) عام میں وائلڈ کارڈز - 1آئیے ایک مثال دیکھتے ہیں:

public class Main {

   public static void main(String[] args) {
      
       String str = new String("Test!");
       // No problem
       Object obj = str;
      
       List<String> strings = new ArrayList<String>();
       // Compilation error!
       List<Object> objects = strings;
   }
}
یہاں کیا ہو رہا ہے؟ ہم دو بہت ملتے جلتے حالات دیکھتے ہیں۔ صورت میں، ہم ایک Stringاعتراض کو ایک Objectاعتراض کاسٹ کرتے ہیں. یہاں کوئی مسئلہ نہیں ہے - ہر چیز توقع کے مطابق کام کرتی ہے۔ لیکن دوسری صورت حال میں، مرتب کرنے والا ایک غلطی پیدا کرتا ہے۔ لیکن ہم ایک ہی کام کر رہے ہیں، کیا ہم نہیں ہیں؟ اس بار ہم صرف کئی اشیاء کا مجموعہ استعمال کر رہے ہیں۔ لیکن غلطی کیوں ہوتی ہے؟ کیا فرق ہے؟ کیا ہم ایک چیز کو ایک یا 20 اشیاء Stringپر ڈال رہے ہیں؟ کسی چیز اور اشیاء کے مجموعےObject کے درمیان ایک اہم فرق ہے ۔ اگر کلاس کلاس کا بچہ ہے ، تو اس کا بچہ نہیں ہے ۔ یہی وجہ ہے کہ ہم اپنا کاسٹ کرنے کے قابل نہیں تھے ۔ کا بچہ ہے ، لیکن کا بچہ نہیں ہے ۔ یہ انتہائی بدیہی معلوم نہیں ہوسکتا ہے۔ زبان کے تخلیق کاروں نے اسے اس طرح کیوں بنایا؟ آئیے تصور کریں کہ کمپائلر ہمیں غلطی نہیں دیتا ہے: BACollection<B>Collection<A>List<String>List<Object>StringObjectList<String>List<Object>

List<String> strings = new ArrayList<String>();
List<Object> objects = strings;
اس صورت میں، ہم، مثال کے طور پر، درج ذیل کام کر سکتے ہیں:

objects.add(new Object());
String s = strings.get(0);
چونکہ مرتب کرنے والے نے ہمیں کوئی غلطی نہیں دی اور ہمیں ایک List<Object>حوالہ بنانے کی اجازت دی جس کی طرف اشارہ کیا گیا ہے strings، ہم مجموعہ میں کوئی بھی پرانی Objectچیز شامل کر سکتے ہیں strings! اس طرح، ہم نے یہ گارنٹی کھو دی ہے کہ ہمارے مجموعے میں صرف وہی Stringچیزیں شامل ہیں جو عام قسم کی درخواست میں قسم کی دلیل کے ذریعہ بیان کی گئی ہیں ۔ دوسرے لفظوں میں، ہم نے جنرک یعنی قسم کی حفاظت کا بنیادی فائدہ کھو دیا ہے۔ اور چونکہ کمپائلر نے ہمیں ایسا کرنے سے نہیں روکا، ہمیں صرف رن ٹائم پر ایک ایرر ملے گا، جو کہ کمپائلیشن ایرر سے کہیں زیادہ بدتر ہوتی ہے۔ اس طرح کے حالات کو روکنے کے لیے، مرتب کرنے والا ہمیں ایک غلطی دیتا ہے:

// Compilation error
List<Object> objects = strings;
...اور ہمیں یاد دلاتا ہے کہ اس List<String>کی اولاد نہیں ہے List<Object>۔ یہ generics کے لیے ایک فولادی اصول ہے، اور ان کے ساتھ کام کرتے وقت اسے یاد رکھنا چاہیے۔ آئیے آگے بڑھیں۔ فرض کریں کہ ہمارے پاس ایک چھوٹا کلاس درجہ بندی ہے:

public class Animal {

   public void feed() {

       System.out.println("Animal.feed()");
   }
}

public class Pet extends Animal {

   public void call() {

       System.out.println("Pet.call()");
   }
}

public class Cat extends Pet {

   public void meow() {

       System.out.println("Cat.meow()");
   }
}
درجہ بندی ایک سادہ جانوروں کی کلاس کے ذریعہ سرفہرست ہے، جو پالتو جانوروں کو وراثت میں ملی ہے۔ پالتو جانوروں کے 2 ذیلی طبقات ہیں: کتا اور بلی۔ اب فرض کریں کہ ہمیں ایک آسان iterateAnimals()طریقہ بنانے کی ضرورت ہے۔ Animalطریقہ کار کو کسی بھی جانور ( , Pet, Cat, ) کا مجموعہ لینا چاہیے Dog، تمام عناصر پر اعادہ کرنا چاہیے، اور ہر تکرار کے دوران کنسول پر ایک پیغام ڈسپلے کرنا چاہیے۔ آئیے ایسا طریقہ لکھنے کی کوشش کرتے ہیں:

public static void iterateAnimals(Collection<Animal> animals) {

   for(Animal animal: animals) {

       System.out.println("Another iteration in the loop!");
   }
}
ایسا لگتا ہے کہ مسئلہ حل ہو گیا ہے! تاہم، جیسا کہ ہم نے حال ہی میں سیکھا ہے، List<Cat>اور List<Dog>اس List<Pet>کی اولاد نہیں ہیں List<Animal>! اس کا مطلب یہ ہے کہ جب ہم iterateAnimals()بلیوں کی فہرست کے ساتھ طریقہ کو کال کرنے کی کوشش کرتے ہیں، تو ہمیں ایک تالیف کی خرابی ملتی ہے:

import java.util.*;

public class Main3 {


   public static void iterateAnimals(Collection<Animal> animals) {

       for(Animal animal: animals) {

           System.out.println("Another iteration in the loop!");
       }
   }

   public static void main(String[] args) {


       List<Cat> cats = new ArrayList<>();
       cats.add(new Cat());
       cats.add(new Cat());
       cats.add(new Cat());
       cats.add(new Cat());

       // Compilation error!
       iterateAnimals(cats);
   }
}
ہمارے لیے حالات بہت اچھے نہیں لگتے! کیا ہمیں ہر قسم کے جانور کی گنتی کے لیے الگ الگ طریقے لکھنے ہوں گے؟ اصل میں، نہیں، ہم ایسا نہیں کرتے :) اور جیسا کہ یہ ہوتا ہے، وائلڈ کارڈ اس میں ہماری مدد کرتے ہیں! ہم مندرجہ ذیل تعمیر کا استعمال کرتے ہوئے ایک آسان طریقہ سے مسئلہ حل کر سکتے ہیں:

public static void iterateAnimals(Collection<? extends Animal> animals) {

   for(Animal animal: animals) {

       System.out.println("Another iteration in the loop!");
   }
}
یہ وائلڈ کارڈ ہے۔ مزید واضح طور پر، یہ وائلڈ کارڈز کی کئی اقسام میں سے پہلا ہے۔ اسے اوپری باؤنڈڈ وائلڈ کارڈز کے نام سے جانا جاتا ہے اور اس کا اظہار کیا جاتا ہے ؟ توسیع کرتا ہے یہ تعمیر ہمیں کیا بتاتی ہے؟ اس کا مطلب یہ ہے کہ طریقہ Animalاشیاء کے مجموعے یا کسی بھی طبقے کی اشیاء کے مجموعہ کو قبول کرتا ہے جو Animal(? توسیع شدہ جانور) سے آتا ہے۔ دوسرے الفاظ میں، طریقہ Animal, Pet, Dog, یا Catاشیاء کے مجموعے کو قبول کر سکتا ہے — اس سے کوئی فرق نہیں پڑتا۔ آئیے خود کو قائل کریں کہ یہ کام کرتا ہے:

public static void main(String[] args) {

   List<Animal> animals = new ArrayList<>();
   animals.add(new Animal());
   animals.add(new Animal());

   List<Pet> pets = new ArrayList<>();
   pets.add(new Pet());
   pets.add(new Pet());

   List<Cat> cats = new ArrayList<>();
   cats.add(new Cat());
   cats.add(new Cat());

   List<Dog> dogs = new ArrayList<>();
   dogs.add(new Dog());
   dogs.add(new Dog());

   iterateAnimals(animals);
   iterateAnimals(pets);
   iterateAnimals(cats);
   iterateAnimals(dogs);
}
کنسول آؤٹ پٹ:

Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
Another iteration in the loop!
ہم نے کل 4 مجموعے اور 8 آبجیکٹ بنائے ہیں، اور کنسول پر بالکل 8 اندراجات ہیں۔ سب کچھ بہت اچھا کام کرتا ہے! :) وائلڈ کارڈ نے ہمیں مخصوص اقسام سے جڑی ضروری منطق کو ایک ہی طریقہ میں آسانی سے فٹ کرنے کی اجازت دی۔ ہم نے ہر قسم کے جانور کے لیے الگ طریقہ لکھنے کی ضرورت کو ختم کر دیا۔ تصور کریں کہ اگر ہماری درخواست چڑیا گھر یا ویٹرنری آفس کے ذریعہ استعمال کی جاتی تو ہمیں کتنے طریقوں کی ضرورت ہوتی :) لیکن اب آئیے ایک مختلف صورتحال کو دیکھتے ہیں۔ ہمارا وراثت کا درجہ بندی بدستور برقرار ہے: اعلی درجے کی کلاس ہے ، بالکل نیچے کی کلاس Animalکے ساتھ ، اور اگلے درجے پر کلاسز۔ اب آپ کو طریقہ کو دوبارہ لکھنے کی ضرورت ہے تاکہ کتوں کے علاوہ کسی بھی قسم کے جانور کے ساتھ کام کریں ۔ یعنی اسے قبول کرنا چاہیے ، یا ، لیکن اس کے ساتھ کام نہیں کرنا چاہیے ۔ ہم یہ کیسے حاصل کر سکتے ہیں؟ ایسا لگتا ہے کہ ہمیں ایک بار پھر ہر قسم کے لیے الگ طریقہ لکھنے کے امکانات کا سامنا ہے:/ ہم مرتب کرنے والے کو کیسے سمجھائیں کہ ہم کیا ہونا چاہتے ہیں؟ یہ اصل میں بہت آسان ہے! ایک بار پھر، وائلڈ کارڈز یہاں ہماری مدد کے لیے آتے ہیں۔ لیکن اس بار ہم ایک اور قسم کے وائلڈ کارڈ کا استعمال کریں گے — ایک نچلے حصے والا وائلڈ کارڈ ، جس کا اظہار سپر کے ذریعے کیا جاتا ہے ۔ PetCatDogiterateAnimals()Collection<Animal>Collection<Pet>Collection<Car>Collection<Dog>

public static void iterateAnimals(Collection<? super Cat> animals) {

   for(int i = 0; i < animals.size(); i++) {

       System.out.println("Another iteration in the loop!");
   }
}
یہاں اصول ایک جیسا ہے۔ کنسٹرکٹ <? super Cat>کمپائلر کو بتاتا ہے کہ iterateAnimals()طریقہ ان پٹ کے طور پر اشیاء کے مجموعہ Catیا Catکلاس کے کسی بھی اجداد کو بطور ان پٹ قبول کر سکتا ہے۔ اس صورت میں، Catکلاس، اس کے والدین Pet، اور اس کے والدین کے والدین، Animalسبھی اس تفصیل سے مماثل ہیں۔ کلاس Dogہماری پابندی سے مماثل نہیں ہے، لہذا List<Dog>دلیل کے ساتھ طریقہ استعمال کرنے کی کوشش کے نتیجے میں تالیف کی خرابی ہوگی:

public static void main(String[] args) {

   List<Animal> animals = new ArrayList<>();
   animals.add(new Animal());
   animals.add(new Animal());

   List<Pet> pets = new ArrayList<>();
   pets.add(new Pet());
   pets.add(new Pet());

   List<Cat> cats = new ArrayList<>();
   cats.add(new Cat());
   cats.add(new Cat());

   List<Dog> dogs = new ArrayList<>();
   dogs.add(new Dog());
   dogs.add(new Dog());

   iterateAnimals(animals);
   iterateAnimals(pets);
   iterateAnimals(cats);
  
   // Compilation error!
   iterateAnimals(dogs);
}
ہم نے اپنا مسئلہ حل کر لیا ہے، اور ایک بار پھر وائلڈ کارڈز انتہائی کارآمد ثابت ہوئے :) اس کے ساتھ ہی سبق ختم ہو گیا ہے۔ اب آپ دیکھتے ہیں کہ جاوا کے آپ کے مطالعے میں جنرکس کتنی اہم ہیں — ہمارے پاس ان کے بارے میں 4 مکمل اسباق ہیں! لیکن اب آپ کو اس موضوع پر اچھی طرح عبور حاصل ہے اور آپ نوکری کے انٹرویوز میں اپنی صلاحیتوں کو ثابت کر سکتے ہیں :) اور اب، کاموں پر واپس جانے کا وقت ہے! اپنی پڑھائی میں بہترین کامیابی! :)
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION