JavaRush /جاوا بلاگ /Random-SD /جاوا ۾ عام ڇا آهن

جاوا ۾ عام ڇا آهن

گروپ ۾ شايع ٿيل
سلام! اڄ اسان generics جي باري ۾ ڳالهائي ويندي. مون کي ضرور چوڻ گهرجي ته توهان تمام گهڻيون نيون شيون سکندا! نه رڳو اهو، پر ايندڙ ڪجهه ليڪچر به جنريڪس لاءِ وقف ڪيا ويندا. جاوا ۾ عام ڇا آهن - 1 تنهن ڪري، جيڪڏهن هي موضوع توهان لاء دلچسپ آهي، توهان خوش قسمت آهيو: اڄ توهان generics جي خاصيتن بابت گهڻو ڪجهه سکندا. خير، جيڪڏهن نه، آرام ڪر ۽ آرام ڪر! :) هي هڪ تمام اهم موضوع آهي ۽ توهان کي ان کي ڄاڻڻ جي ضرورت آهي. اچو ته هڪ سادي سان شروع ڪريون: "ڇا" ۽ "ڇو". generics ڇا آهن؟ جنريڪس قسم جا پيرا ميٽر آهن. جڏهن هڪ عام ٺاهي، توهان نه صرف ان جو قسم بيان ڪيو، پر ڊيٽا جو قسم پڻ ان سان گڏ ڪم ڪرڻ گهرجي. منهنجو خيال آهي ته سڀ کان وڌيڪ واضح مثال اڳ ۾ ئي توهان جي ذهن ۾ اچي چڪو آهي - هي آهي ArrayList! هتي اهو آهي ته اسان عام طور تي ان کي پروگرام ۾ ڪيئن ٺاهيندا آهيون:
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<String> myList1 = new ArrayList<>();
       myList1.add("Test String 1");
       myList1.add("Test String 2");
   }
}
جئين توهان اندازو لڳائي سگهو ٿا، فهرست جي خاصيت اها آهي ته اهو ممڪن نه هوندو ته هر شيء کي "سامان" ۾ شامل ڪرڻ: اهو خاص طور تي ڪم ڪري ٿو شين سان String. هاڻي اچو ته جاوا جي تاريخ ۾ هڪ مختصر سير ڪريون ۽ ان سوال جو جواب ڏيڻ جي ڪوشش ڪريون: ”ڇو؟ هن کي ڪرڻ لاء، اسان پاڻ کي ArrayList طبقي جو هڪ آسان نسخو لکنداسين. اسان جي لسٽ صرف اندروني صف ۾ ڊيٽا شامل ڪري سگهي ٿي ۽ هي ڊيٽا حاصل ڪري سگهي ٿي:
public class MyListClass {

   private Object[] data;
   private int count;

   public MyListClass() {
       this.data = new Object[10];
       this.count = 0;
   }

   public void add(Object o) {
       this.data[count] = o;
       count++;
   }

   public Object[] getData() {
       return data;
   }
}
اچو ته چئون ته اسان چاهيون ٿا ته اسان جي لسٽ صرف نمبرن کي ذخيرو ڪرڻ لاء Integer. اسان وٽ عام نه آهن. اسان واضح طور تي بيان نه ٿا ڪري سگھون o مثال جي چڪاس Integer۾ add(). پوءِ اسان جو سڄو ڪلاس صرف لاءِ موزون هوندو Integer، ۽ اسان کي دنيا ۾ موجود سڀني ڊيٽا جي قسمن لاءِ ساڳيو ڪلاس لکڻو پوندو! اسان فيصلو ڪريون ٿا ته اسان جي پروگرامرز تي ڀروسو ڪيو وڃي ۽ صرف ڪوڊ ۾ هڪ تبصرو ڇڏي ڏيو ته جيئن اهي اتي ڪا به غير ضروري شامل نه ڪن:
//use it ONLY with Integer data type
public void add(Object o) {
   this.data[count] = o;
   count++;
}
هڪ پروگرامر اهو تبصرو وڃائي ڇڏيو ۽ اڻڄاڻ طور تي لسٽ ۾ تارن سان مليل انگن کي رکڻ جي ڪوشش ڪئي، ۽ پوء انهن جي رقم کي ڳڻيو:
public class Main {

   public static void main(String[] args) {

       MyListClass list = new MyListClass();
       list.add(100);
       list.add(200);
       list.add("Lolkek");
       list.add("Shalala");

       Integer sum1 = (Integer) list.getData()[0] + (Integer) list.getData()[1];
       System.out.println(sum1);

       Integer sum2 = (Integer) list.getData()[2] + (Integer) list.getData()[3];
       System.out.println(sum2);
   }
}
ڪنسول آئوٽ: 300 Exception in the thread "main" java.lang.ClassCastException: java.lang.String کي java.lang.Integer تي ڪاسٽ نٿو ڪري سگھجي Main.main(Main.java:14) هن صورتحال ۾ سڀ کان وڌيڪ خراب ڇا آهي؟ پروگرامر جي غفلت کان پري. بدترين شيء اها آهي ته غلط ڪوڊ اسان جي پروگرام ۾ هڪ اهم جاء تي ختم ٿي ويو ۽ ڪاميابي سان مرتب ڪيو ويو . ھاڻي اسان ڏسنداسين نقص ڪوڊنگ اسٽيج تي نه، پر رڳو ٽيسٽنگ اسٽيج تي (۽ اھو بھترين صورت ۾ آھي!). بگ کي درست ڪرڻ بعد ۾ ترقي ۾ تمام گهڻو خرچ ٿئي ٿو - پئسا ۽ وقت ٻئي. اهو خاص طور تي generics جو فائدو آهي: هڪ عام ڪلاس هڪ بدقسمت پروگرامر کي فوري طور تي هڪ غلطي ڳولڻ جي اجازت ڏيندو. ڪوڊ صرف گڏ نه ڪندو!
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Integer> myList1 = new ArrayList<>();

       myList1.add(100);
       myList1.add(100);
       myList1.add("Lolkek");//error!
       myList1.add("Shalala");//error!
   }
}
پروگرامر فوري طور تي "پنهنجي هوش ۾ اچي" ۽ فوري طور تي پاڻ کي درست ڪندو. رستي ۾، Listهن قسم جي غلطي کي ڏسڻ لاء اسان کي پنهنجو طبقو ٺاهڻ جي ضرورت نه هئي. بس ٽائپ بریکٹ ( <Integer>) کي باقاعده ArrayList مان هٽايو!
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

      List list = new ArrayList();

      list.add(100);
      list.add(200);
      list.add("Lolkek");
      list.add("Shalala");

       System.out.println((Integer) list.get(0) + (Integer) list.get(1));
       System.out.println((Integer) list.get(2) + (Integer) list.get(3));
   }
}
ڪنسول آئوٽ: 300 Exception in the thread "main" java.lang.ClassCastException: java.lang.String کي java.lang.Integer ۾ ڪاسٽ نٿو ڪري سگھجي Main.main(Main.java:16) يعني ”مقامي“ اوزار استعمال ڪندي جاوا، توهان هن غلطي ڪري سگهو ٿا ۽ هڪ غير محفوظ مجموعو ٺاهي سگهو ٿا. بهرحال، جيڪڏهن اسان هن ڪوڊ کي IDEa ۾ پيسٽ ڪريون ٿا، اسان کي هڪ ڊيڄاريندڙ نظر اچي ٿي: " جاوا.util.List جي خام قسم جي ميمبر جي طور تي شامل ڪرڻ لاءِ اڻ چيڪ ٿيل ڪال " اهو اسان کي ٻڌائي ٿو ته هڪ عنصر شامل ڪرڻ وقت ڪجهه غلط ٿي سگهي ٿو. generics کان سواء گڏ ڪرڻ هن طريقي سان نه. پر لفظ ڇا آهي "خام قسم" جو مطلب آهي؟ لفظي ترجمو بلڪل صحيح ٿيندو - " خام قسم " يا " گندي قسم ". Raw typeھڪڙو عام طبقو آھي جنھن مان ان جو قسم ختم ڪيو ويو آھي. ٻين لفظن ۾، List myList1هي آهي Raw type. سامهون هڪ عام طبقو raw typeآهي generic type(جنهن کي هڪ طبقي جي نالي سان پڻ سڃاتو وڃي ٿو parameterized type)، صحيح طور تي ٺهيل، هڪ قسم جي وضاحت سان. مثال طور، List<String> myList1. توھان وٽ ھڪڙو سوال ٿي سگھي ٿو: ڇو ان کي استعمال ڪرڻ جي اجازت آھي raw types؟ سبب سادو آهي. جاوا جي ٺاهيندڙن ٻولي ۾ مدد ڇڏي ڏني raw typesته جيئن مطابقت مسئلا پيدا نه ڪن. ان وقت تائين جاوا 5.0 جاري ڪيو ويو (جنريڪس هن نسخي ۾ پهريون ڀيرو ظاهر ٿيو)، گهڻو ڪري ڪوڊ اڳ ۾ ئي استعمال ڪندي لکيو ويو هو raw types. تنهن ڪري، اهو امڪان اڄ به موجود آهي. اسان اڳ ۾ ئي ذڪر ڪيو آهي جوشوا بلوچ جي شاندار ڪتاب ”اثر جاوا“ هڪ کان وڌيڪ ڀيرا ليڪچرن ۾. ٻوليءَ جي تخليقڪارن مان هڪ هئڻ ڪري، هن ڪتاب ۾ استعمال raw types۽ استعمال جي موضوع کي نظرانداز نه ڪيو generic types. جاوا ۾ عام ڇا آهن - 2هن ڪتاب جي باب 23 جو هڪ تمام فصيح عنوان آهي: ”نئين ڪوڊ ۾ خام قسمون استعمال نه ڪريو.“ هي ڪجهه آهي جيڪو توهان کي ياد رکڻ جي ضرورت آهي. جڏهن عام طبقن کي استعمال ڪندي، انهن کي ڪڏهن به تبديل نه generic typeڪريو raw type.

ٽائپ ٿيل طريقا

جاوا توهان کي انفرادي طريقن کي ٽائپ ڪرڻ جي اجازت ڏئي ٿو، نام نهاد عام طريقا ٺاهيندي. ڇو اهڙيون طريقا آسان آهن؟ سڀ کان پهريان، ڇاڪاڻ ته اهي توهان کي مختلف قسم جي پيٽرولن سان ڪم ڪرڻ جي اجازت ڏين ٿا. جيڪڏهن ساڳيو منطق مختلف قسمن تي محفوظ طور تي لاڳو ڪري سگهجي ٿو، هڪ عام طريقو هڪ بهترين حل آهي. اچو ته هڪ مثال ڏسو. اچو ته اسان وٽ ڪجهه قسم جي فهرست آهي myList1. اسان ان مان سڀ قدر ختم ڪرڻ چاهيون ٿا، ۽ سڀني خالي جڳهن کي نئين قيمت سان ڀريو. هي اهو آهي جيڪو اسان جي ڪلاس سان عام طريقي سان نظر ايندو:
public class TestClass {

   public static <T> void fill(List<T> list, T val) {
       for (int i = 0; i < list.size(); i++)
           list.set(i, val);
   }

   public static void main(String[] args) {

       List<String> strings = new ArrayList<>();
       strings.add("Старая строка 1");
       strings.add("Старая строка 2");
       strings.add("Старая строка 3");

       fill(strings, "Новая строка");

       System.out.println(strings);

       List<Integer> numbers = new ArrayList<>();
       numbers.add(1);
       numbers.add(2);
       numbers.add(3);

       fill(numbers, 888);
       System.out.println(numbers);
   }
}
نحو تي ڌيان ڏيو، اهو ٿورڙو غير معمولي نظر اچي ٿو:
public static <T> void fill(List<T> list, T val)
واپسي جو قسم <T> کان اڳ آهي، جيڪو هڪ عام طريقو ظاهر ڪري ٿو. ان صورت ۾، طريقو 2 پيرا ميٽرن کي انپٽ طور وٺي ٿو: شين جي هڪ فهرست T ۽ ٻي الڳ شئي T. <T> استعمال ڪندي، طريقي جي ٽائپنگ حاصل ڪئي وئي آهي: اسان اتي تارن جي فهرست ۽ نمبر پاس نٿا ڪري سگهون. تارن جي هڪ فهرست ۽ هڪ تار، انگن جي هڪ فهرست ۽ هڪ نمبر، اسان جي شين جي هڪ فهرست Cat۽ ٻيو اعتراض Cat- اهو ئي واحد طريقو آهي. اهو طريقو main()واضح طور تي ظاهر ڪري ٿو ته اهو طريقو fill()آساني سان ڪم ڪري ٿو مختلف قسمن جي ڊيٽا سان. پهرين، اهو ان پٽ طور وٺندو آهي تارن جي هڪ فهرست ۽ هڪ اسٽرنگ، ۽ پوءِ انگن ۽ انگن جي هڪ فهرست. ڪنسول آئوٽ: [نئين لائن، نيو لائن، نيو لائن] [888، 888، 888] تصور ڪريو جيڪڏهن fill()اسان کي 30 مختلف طبقن لاءِ طريقي جي منطق جي ضرورت آهي، ۽ اسان وٽ عام طريقا نه آهن. اسان کي 30 ڀيرا ساڳيو طريقو لکڻ تي مجبور ڪيو ويندو، صرف مختلف ڊيٽا جي قسمن لاءِ! پر عام طريقن جي مهرباني، اسان اسان جي ڪوڊ کي ٻيهر استعمال ڪري سگهون ٿا! :)

ٽائپ ٿيل ڪلاس

توهان نه رڳو استعمال ڪري سگهو ٿا عام طبقن جاوا ۾ مهيا ڪيل، پر پڻ پنهنجو ٺاهي سگهو ٿا! هتي هڪ سادي مثال آهي:
public class Box<T> {

   private T t;

   public void set(T t) {
       this.t = t;
   }

   public T get() {
       return t;
   }

   public static void main(String[] args) {

       Box<String> stringBox = new Box<>();

       stringBox.set("Старая строка");
       System.out.println(stringBox.get());
       stringBox.set("Новая строка");

       System.out.println(stringBox.get());

       stringBox.set(12345);//ошибка компиляции!
   }
}
اسان جو ڪلاس Box<T>(“باڪس”) ٽائپ ٿيل آهي. ٺاھڻ دوران ان کي ڊيٽا جو قسم ( ) تفويض ڪرڻ سان <T>، اسان ھاڻي ان ۾ ٻين قسمن جون شيون رکي نه سگھنداسون. اهو مثال ۾ ڏسي سگهجي ٿو. جڏهن ٺاهي، اسان بيان ڪيو ته اسان جو اعتراض تارن سان ڪم ڪندو:
Box<String> stringBox = new Box<>();
۽ جڏهن ڪوڊ جي آخري لائين ۾ اسان نمبر 12345 کي دٻي جي اندر رکڻ جي ڪوشش ڪندا آهيون، اسان کي گڏ ڪرڻ جي غلطي ملي ٿي! بس انهي وانگر، اسان پنهنجو پنهنجو عام ڪلاس ٺاهيو! :) هي اڄ اسان جي ليڪچر کي ختم ڪري ٿو. پر اسان عام کي الوداع نه چئي رهيا آهيون! ايندڙ ليڪچرن ۾ اسان وڌيڪ جديد خصوصيتن بابت ڳالهائينداسين، تنهنڪري الوداع نه چئو! ) توهان جي پڙهائي ۾ سٺي قسمت! :)
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION