JavaRush /جاوا بلاگ /Random-SD /جاوا جنريڪس ۾ وائلڊ ڪارڊ

جاوا جنريڪس ۾ وائلڊ ڪارڊ

گروپ ۾ شايع ٿيل
سلام! اسان generics جي موضوع جو مطالعو جاري رکون ٿا. توهان وٽ اڳئين ليڪچرن مان انهن جي باري ۾ اڳ ۾ ئي سٺي ڄاڻ آهي ( وارارگ استعمال ڪرڻ بابت جڏهن جنريڪس سان ڪم ڪندي ۽ قسم ختم ڪرڻ بابت )، پر اسان اڃا تائين هڪ اهم موضوع کي ڍڪي نه ڇڏيو آهي: وائلڊ ڪارڊ . هي generics جي هڪ تمام اهم خصوصيت آهي. ايتري قدر جو اسان ان لاءِ الڳ ليڪچر وقف ڪيو آهي! تنهن هوندي به، وائلڊ ڪارڊ بابت ڪا به پيچيدگي ناهي، توهان ڏسندا ته هاڻي :) وائلڊ ڪارڊ عام ۾ - 1اچو ته هڪ مثال ڏسو:
public class Main {

   public static void main(String[] args) {

       String str = new String("Test!");
       // ниHowих проблем
       Object obj = str;

       List<String> strings = new ArrayList<String>();
       // ошибка компиляции!
       List<Object> objects = strings;
   }
}
هتي ڇا ٿي رهيو آهي؟ اسان ٻه تمام گهڻيون حالتون ڏسون ٿا. انهن مان پهرين ۾، اسان Stringٽائپ ڪرڻ لاء هڪ اعتراض اڇلائڻ جي ڪوشش ڪري رهيا آهيون Object. هن سان ڪو به مسئلو ناهي، هر شي ڪم ڪري ٿي جيئن ان کي گهرجي. پر ٻئي صورتحال ۾، مرتب ڪندڙ هڪ غلطي اڇلائي ٿو. جيتوڻيڪ اهو لڳي ٿو ته اسان ساڳيو ڪم ڪري رهيا آهيون. اهو صرف اهو آهي ته هاڻي اسان ڪيترن ئي شين جو مجموعو استعمال ڪري رهيا آهيون. پر غلطي ڇو ٿئي ٿي؟ ڇا فرق آهي، بنيادي طور تي، ڇا اسان هڪ اعتراض کي Stringهڪ قسم Objectيا 20 شين تي اڇلائي؟ ڪنهن شئي ۽ شين جي مجموعن جي وچ ۾ هڪ اهم فرق آهي . جيڪڏهن هڪ طبقو Bهڪ طبقي جو جانشين آهي А، Collection<B>ته پوء اهو هڪ جانشين ناهي Collection<A>. اهو ئي سبب آهي جو اسان پنهنجو پاڻ List<String>کي کڻي نه سگهياسين List<Object>. Stringهڪ وارث آهي Object، پر List<String>هڪ وارث نه آهي List<Object>. وجداني طور تي، اهو بلڪل منطقي نظر نٿو اچي. ٻوليءَ جا تخليقڪار ان اصول جي رهنمائي ڇو ڪندا هئا؟ اچو ته تصور ڪريون ته مرتب ڪندڙ اسان کي هتي غلطي نه ڏيندو:
List<String> strings = new ArrayList<String>();
List<Object> objects = strings;
هن معاملي ۾، اسان ڪري سگهون ٿا، مثال طور، هيٺيون ڪم:
objects.add(new Object());
String s = strings.get(0);
جيئن ته مرتب ڪندڙ اسان کي غلطيون نه ڏنيون آهن ۽ اسان کي List<Object> objectاسٽرنگ جي مجموعي لاء هڪ حوالو ٺاهڻ جي اجازت ڏني آهي strings، اسان stringsهڪ اسٽرنگ نه، پر صرف ڪنهن به اعتراض کي شامل ڪري سگهون ٿا Object! ان ڪري، اسان اها گارنٽي وڃائي چڪا آهيون ته اسان جي مجموعي ۾ صرف اهي شيون شامل آهن جيڪي عام ۾ بيان ڪيل آهنString . اھو آھي، اسان generics جو بنيادي فائدو وڃائي ڇڏيو آھي - قسم جي حفاظت. ۽ جيئن ته مرتب ڪندڙ اسان کي اهو سڀ ڪرڻ جي اجازت ڏني آهي، ان جو مطلب اهو آهي ته اسان کي صرف پروگرام جي عمل جي دوران هڪ غلطي ملندي، جيڪا هميشه هڪ تاليف جي غلطي کان وڌيڪ خراب آهي. اهڙين حالتن کي روڪڻ لاء، مرتب ڪندڙ اسان کي هڪ غلطي ڏئي ٿو:
// ошибка компиляции
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("Еще один шаг в цикле пройден!");
   }
}
لڳي ٿو ته مسئلو حل ٿي ويو آهي! بهرحال، جيئن اسان تازو معلوم ڪيو، 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("Еще один шаг в цикле пройден!");
       }
   }

   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());

       //ошибка компилятора!
       iterateAnimals(cats);
   }
}
حالتون اسان لاءِ سٺيون نظر نٿيون اچن! اهو معلوم ٿئي ٿو ته اسان کي سڀني قسمن جي جانورن جي ڳڻپ لاء الڳ طريقا لکڻو پوندو؟ حقيقت ۾، نه، توهان کي ڪرڻ جي ضرورت ناهي :) ۽ وائلڊ ڪارڊ اسان جي مدد ڪندا ! اسان هڪ سادي طريقي سان مسئلو حل ڪنداسين، هيٺ ڏنل تعمير استعمال ڪندي:
public static void iterateAnimals(Collection<? extends Animal> animals) {

   for(Animal animal: animals) {

       System.out.println("Еще один шаг в цикле пройден!");
   }
}
هي وائلڊ ڪارڊ آهي. وڌيڪ واضح طور تي، هي وائلڊ ڪارڊ جي ڪيترن ئي قسمن مان پهريون آهي - " extensions " (ٻيو نالو آهي اپر بائونڊڊ وائلڊ ڪارڊ ). هي ڊزائن اسان کي ڇا ٻڌائي ٿو؟ Animalهن جو مطلب اهو آهي ته اهو طريقو ڪنهن به نسل جي طبقي جي شين يا شين جو مجموعو داخل ڪري ٿو Animal (? extends Animal). ٻين لفظن ۾، طريقو مجموعو قبول ڪري سگھي ٿو Animal، يا ان پٽ جي طور تي - ان سان ڪو به فرق نٿو پوي. اچو ته پڪ ڪريو ته هي ڪم ڪري ٿو: PetDogCat
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);
}
ڪنسول آئوٽ:

Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
Еще один шаг в цикле пройден!
اسان مجموعي طور تي 4 مجموعا ۽ 8 شيون ٺاھيون آھن، ۽ ڪنسول ۾ بلڪل 8 داخلون آھن. هر شي عظيم ڪم ڪري ٿو! :) وائلڊ ڪارڊ اسان کي اجازت ڏني ته آسانيءَ سان ضروري منطق کي هڪ طريقي سان مخصوص قسمن جي پابند ڪرڻ سان. اسان کي هر قسم جي جانور لاءِ الڳ طريقو لکڻ جي ضرورت محسوس ٿي. تصور ڪريو ته اسان وٽ ڪيترا طريقا آھن جيڪڏھن اسان جي ايپليڪيشن زو يا جانورن جي ڪلينڪ ۾ استعمال ٿئي ها :) ھاڻي اچو ته ھڪڙي مختلف صورتحال تي نظر رکون. اسان جي وراثت جو درجو ساڳيو ئي رهندو: مٿين سطح جو طبقو آهي Animal، صرف هيٺيون طبقو پالتو جانور آهي Pet، ۽ ايندڙ سطح تي آهي Cat۽ Dog. ھاڻي توھان کي ھن طريقي کي ٻيهر لکڻو پوندو iretateAnimals()ته جيئن اھو ڪتن کان سواءِ ڪنھن به قسم جي جانور سان ڪم ڪري سگھي . Collection<Animal>اهو آهي، ان کي قبول ڪرڻ گهرجي ، Collection<Pet>يا ان پٽ جي طور تي Collection<Cat>، پر ڪم نه ڪرڻ گهرجي Collection<Dog>. اسان اهو ڪيئن حاصل ڪري سگهون ٿا؟ اهو لڳي ٿو ته هر قسم لاء هڪ الڳ طريقو لکڻ جو امڪان اسان جي اڳيان ٻيهر آهي:/ ٻيو ڪيئن اسان پنهنجي منطق کي مرتب ڪرڻ واري کي وضاحت ڪري سگهون ٿا؟ ۽ اهو بلڪل آسان ٿي سگهي ٿو! هتي وائلڊ ڪارڊ وري اسان جي مدد لاءِ ايندا. پر هن ڀيري اسان هڪ مختلف قسم استعمال ڪنداسين - “ سپر ” (ٻيو نالو آهي لوئر بائونڊڊ وائلڊ ڪارڊ ).
public static void iterateAnimals(Collection<? super Cat> animals) {

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

       System.out.println("Еще один шаг в цикле пройден!");
   }
}
اصول هتي ساڳيو آهي. تعميراتي <? super Cat>ڪمپليٽر کي ٻڌائي ٿو ته طريقو iterateAnimals()ان پٽ طور وٺي سگھي ٿو ڪلاس Catيا ڪنهن ٻئي اباڻي طبقي جي شين جو مجموعو Cat. Catاسان جي حالت ۾، طبقو پاڻ ، ان جو اباڻو - Pets، ۽ ابن ڏاڏن جو - هن وضاحت سان ٺهڪي اچي ٿو 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);

   //ошибка компиляции!
   iterateAnimals(dogs);
}
اسان جو مسئلو حل ٿي ويو آهي، ۽ ٻيهر وائلڊ ڪارڊ انتهائي مفيد ثابت ٿيو :) هي ليڪچر ختم ڪري ٿو. ھاڻي توھان ڏسو ته جاوا سکڻ وقت جنريڪس جو موضوع ڪيترو ضروري آھي - اسان ان تي 4 ليڪچر ڏنا! پر ھاڻي توھان وٽ موضوع جي سٺي سمجھ آھي ۽ توھان پاڻ کي انٽرويو ۾ ثابت ڪرڻ جي قابل ٿي ويندا :) ۽ ھاڻي وقت آھي ڪمن ڏانھن موٽڻ جو! توهان جي پڙهائي ۾ سٺي قسمت! :)
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION