سلام اچو ته generics جو مطالعو جاري رکون. توھان اڳئين سبقن مان انھن جي باري ۾ ڪافي ڄاڻ حاصل ڪري چڪا آھيو ( جڏھن generics سان ڪم ڪرڻ وقت varargs استعمال ڪرڻ
بابت ۽ قسم erasure
جي باري ۾ )، پر ھڪڙو اھم موضوع آھي جنھن تي اسان اڃا غور نہ ڪيو آھي - وائلڊ ڪارڊ . هي generics جي تمام اهم خصوصيت آهي. ايتري قدر جو اسان ان لاءِ هڪ الڳ سبق وقف ڪيو آهي! اهو چيو ته، وائلڊ ڪارڊ بابت خاص طور تي پيچيده ڪجھ به ناهي. توهان اهو ڏسندا ته فوري طور تي :)
اچو ته هڪ مثال ڏسو:

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
جي وچ ۾ هڪ اهم فرق آهي . جيڪڏهن ڪلاس ڪلاس جو ٻار آهي ته پوءِ ڪلاس جو ٻار ناهي . اهو ئي سبب آهي جو اسان پنهنجي ڪاسٽ ڪرڻ جي قابل نه هئاسين . جو ٻار آهي ، پر جو ٻار ناهي . اهو شايد سپر وجداني نه لڳي. ٻوليءَ جي تخليقڪارن ائين ڇو ڪيو؟ اچو ته تصور ڪريون ته مرتب ڪندڙ اسان کي غلطي نه ڏئي: B
A
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>
حوالو ٺاهڻ جي اجازت ڏني جيڪا اشارو ڪري ٿي strings
، اسان مجموعي Object
۾ ڪنهن به پراڻي اعتراض کي شامل ڪري سگهون ٿا strings
! ان ڪري، اسان اها گارنٽي وڃائي چڪا آهيون ته اسان جي مجموعن ۾ صرف اهي String
شيون شامل آهن جيڪي عام قسم جي دعوت ۾ قسم جي دليل طرفان بيان ڪيل آهن . ٻين لفظن ۾، اسان generics جو بنيادي فائدو وڃائي ڇڏيو آهي - قسم جي حفاظت. ۽ ڇاڪاڻ ته مرتب ڪندڙ اسان کي ائين ڪرڻ کان نه روڪيو، اسان کي صرف رن ٽائيم تي هڪ غلطي ملندي، جيڪا هميشه هڪ تاليف جي غلطي کان وڌيڪ خراب آهي. اهڙين حالتن کي روڪڻ لاء، مرتب ڪندڙ اسان کي هڪ غلطي ڏئي ٿو:
// Compilation error
List<Object> objects = strings;
...۽ اسان کي ياد ڏياريندو آهي ته ان List<String>
جو اولاد ناهي List<Object>
. هي عام ماڻهن لاءِ هڪ لوهه جو قاعدو آهي، ۽ اهو ياد رکڻ گهرجي جڏهن انهن سان ڪم ڪيو وڃي. اچو ته اڳتي وڌون. فرض ڪريو اسان وٽ ھڪڙو ننڍڙو طبقو آھي:
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
، Pet
صرف هيٺئين طبقي سان، ۽ Cat
ايندڙ Dog
سطح تي طبقن سان. ھاڻي توھان کي ھن طريقي کي ٻيهر لکڻو پوندو iterateAnimals()
ته جيئن ڪتن کان سواءِ ڪنھن به قسم جي جانور سان ڪم ڪري سگھجي . اهو آهي، ان کي قبول ڪرڻ گهرجي Collection<Animal>
، Collection<Pet>
يا Collection<Car>
، پر ان سان ڪم نه ڪرڻ گهرجي Collection<Dog>
. اسان اهو ڪيئن حاصل ڪري سگهون ٿا؟ اهو لڳي ٿو ته اسان ٻيهر هر قسم جي لاء هڪ الڳ طريقو لکڻ جي امڪان کي منهن ڏئي رهيا آهيون:/ ٻيو ڪيئن اسان مرتب ڪندڙ کي وضاحت ڪريون ٿا ته اسان ڇا ٿيڻ چاهيون ٿا؟ اهو اصل ۾ بلڪل سادو آهي! هڪ ڀيرو ٻيهر، وائلڊ ڪارڊ هتي اسان جي مدد لاء ايندا. پر هن ڀيري اسان هڪ ٻيو قسم جو وائلڊ ڪارڊ استعمال ڪنداسين - هڪ هيٺيون بائونڊڊ وائلڊ ڪارڊ ، جنهن جو اظهار ڪيو ويندو آهي super .
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 مڪمل سبق آھن! پر هاڻي توهان موضوع ۾ چڱي طرح ماهر آهيو ۽ توهان نوڪري جي انٽرويو ۾ توهان جي صلاحيتن کي ثابت ڪري سگهو ٿا :) ۽ هاڻي، اهو وقت آهي ڪمن ڏانهن واپس وڃڻ جو! توهان جي پڙهائي ۾ بهترين ڪاميابي! :)
GO TO FULL VERSION