CodeGym /جاوا بلاگ /Random-SD /جاوا ۾ عام
John Squirrels
سطح
San Francisco

جاوا ۾ عام

گروپ ۾ شايع ٿيل
سلام اسان جاوا جنريڪس بابت ڳالهائڻ وارا آهيون. مون کي ضرور چوڻ گهرجي ته توهان گهڻو ڪجهه سکندا! نه رڳو هي سبق، پر ايندڙ ڪجهه سبق پڻ، جنريڪس ڏانهن وقف ڪيا ويندا. تنهن ڪري، جيڪڏهن توهان generics ۾ دلچسپي رکو ٿا، اڄ توهان جي خوش قسمت ڏينهن آهي: توهان 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;
   }
}
فرض ڪريو اسان چاهيون ٿا ته اسان جي لسٽ صرف انٽيجر s کي ذخيرو ڪرڻ لاءِ. اسان هڪ عام قسم استعمال نه ڪري رهيا آهيون. اسان شامل ڪرڻ نٿا چاهيون هڪ واضح "Instanceof Integer " چيڪ شامل ڪريو () طريقي ۾. جيڪڏهن اسان ائين ڪيو، ته اسان جو سڄو ڪلاس صرف Integer لاءِ موزون هوندو ، ۽ اسان کي دنيا جي هر ٻئي ڊيٽا جي قسم لاءِ هڪ جهڙو ڪلاس لکڻو پوندو! اسان پنهنجي پروگرامرز تي ڀروسو ڪنداسين، ۽ صرف ڪوڊ ۾ هڪ تبصرو ڇڏي ڏيو انهي کي يقيني بڻائڻ لاءِ ته اهي ڪجهه شامل نه ڪن جيڪي اسان نٿا چاهيون:
// Use this class ONLY with the 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 thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
      at Main.main (Main.java:14)
هن صورتحال جو بدترين حصو ڇا آهي؟ يقينن پروگرامر جي لاپرواهي نه آهي. بدترين حصو اهو آهي ته غلط ڪوڊ اسان جي پروگرام ۾ هڪ اهم جاء تي ختم ٿي ويو ۽ ڪاميابي سان مرتب ڪيو ويو. ھاڻي اسان بگ کي منهن ڏينداسين ڪوڊ لکڻ دوران نه، پر صرف جانچ دوران (۽ اھو بھترين صورت حال آھي!). ترقيءَ جي پوئين مرحلن ۾ بگ کي درست ڪرڻ تمام گھڻو خرچ ٿئي ٿو - ٻئي پئسي ۽ وقت جي لحاظ کان. اهو بلڪل صحيح آهي جتي جنريڪس اسان کي فائدو ڏئي ٿو: هڪ عام طبقو بدقسمت پروگرامر کي فوري طور تي غلطي کي ڳولڻ جي اجازت ڏئي ٿو. پروگرام صرف ترتيب نه ڏيندو!
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!
   }
}
پروگرامر کي فوري طور تي پنهنجي غلطي جو احساس ٿئي ٿو ۽ فوري طور تي بهتر ٿي وڃي ٿو. رستي جي ذريعي، اسان کي هن قسم جي غلطي کي ڏسڻ لاء اسان جي پنهنجي لسٽ ڪلاس ٺاهڻ جي ضرورت ناهي . بس زاويه بریکٹ کي هٽايو ۽ ٽائپ ڪريو ( <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 thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
     at Main.main(Main.java:16)
ٻين لفظن ۾، جيتوڻيڪ جاوا جي "مقامي" ميڪانيزم کي استعمال ڪندي، اسان هن قسم جي غلطي ڪري سگهون ٿا ۽ هڪ غير محفوظ مجموعو ٺاهي سگهون ٿا. بهرحال، جيڪڏهن اسان هن ڪوڊ کي IDE ۾ پيسٽ ڪريون ٿا، اسان کي هڪ ڊيڄاريندڙ ملي ٿي: "جاوا.util.List جي خام قسم جي ميمبر جي طور تي شامل ڪرڻ لاءِ اڻ چيڪ ٿيل ڪال" اسان کي ٻڌايو ويو آهي ته شيون شامل ڪرڻ وقت ڪجهه غلط ٿي سگهي ٿو هڪ مجموعي ڏانهن جنهن ۾ عام قسم جي کوٽ ناهي. پر لفظ "خام قسم" جو مطلب ڇا آهي؟ خام قسم ھڪڙو عام طبقو آھي جنھن جو قسم ختم ڪيو ويو آھي. ٻين لفظن ۾، فهرست myList1 هڪ خام قسم آهي . خام قسم جي برعڪس هڪ عام قسم آهي - هڪ عام ڪلاس جنهن جي اشاري سان پيراميٽرائز ٿيل قسم (ص) . مثال طور، List<String> myList1 . توھان پڇي سگھوٿا ته ٻولي خام قسم جي استعمال جي اجازت ڇو ڏئي ٿي ؟ سبب سادو آهي. جاوا جي تخليقڪار مطابقت جي مسئلن کي پيدا ڪرڻ کان بچڻ لاءِ ٻوليءَ ۾ خام قسمن جي حمايت ڇڏي ڏني. ان وقت تائين جاوا 5.0 جاري ڪيو ويو (جنريڪس پهريون ڀيرو هن نسخي ۾ ظاهر ٿيو)، ڪافي ڪوڊ اڳ ۾ ئي لکيا ويا هئا خام قسمون استعمال ڪندي . نتيجي طور، هي ميکانيزم اڃا تائين حمايت ڪئي وئي آهي. اسان سبقن ۾ جوشوا بلوچ جي شاندار ڪتاب ”اثر جاوا“ جو بار بار ذڪر ڪيو آهي. ٻوليءَ جي تخليقڪارن مان هڪ هئڻ ڪري، هن پنهنجي ڪتاب ۾ خام قسم ۽ عام قسمن کي نه ڇڏيو. جاوا ۾ عام ڇا آهن؟  - 2ڪتاب جو باب 23 هڪ تمام فصيح عنوان آهي: "نئين ڪوڊ ۾ خام قسم استعمال نه ڪريو" اهو آهي جيڪو توهان کي ياد رکڻ جي ضرورت آهي. عام طبقن کي استعمال ڪرڻ وقت، ڪڏهن به عام قسم کي خام قسم ۾ نه ڦيرايو .

عام طريقا

جاوا توهان کي نام نهاد عام طريقا ٺاهي انفرادي طريقن کي ترتيب ڏيڻ جي اجازت ڏئي ٿو. اهڙا طريقا ڪيئن مددگار آهن؟ سڀ کان وڌيڪ، اهي مددگار آهن انهي ۾ اهي توهان کي ڪم ڪرڻ جي اجازت ڏين ٿا مختلف قسم جي طريقن جي پيٽرولن سان. جيڪڏهن ساڳيو منطق مختلف قسمن تي محفوظ طور تي لاڳو ڪري سگهجي ٿو، هڪ عام طريقو هڪ بهترين حل ٿي سگهي ٿو. هن هڪ تمام سادي مثال تي غور ڪريو: فرض ڪريو اسان وٽ ڪجهه فهرست آهي جنهن کي 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("Old String 1");
       strings.add("Old String 2");
       strings.add("Old String 3");

       fill(strings, "New String");

       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>، اسان طريقي جي پيراميٽر جي قسمن کي ترتيب ڏيون ٿا: اسان Strings ۽ Integer جي فهرست ۾ پاس نه ٿا ڪري سگھون. Strings ۽ هڪ String جي هڪ فهرست، Integers ۽ هڪ Integer جي هڪ فهرست، اسان جي پنهنجي ٻلي جي شين جي هڪ فهرست ۽ هڪ ٻيو Cat اعتراض - اهو آهي جيڪو اسان کي ڪرڻو آهي. main () طريقو بيان ڪري ٿو ته ڪيئن fill() طريقو آساني سان استعمال ڪري سگهجي ٿو مختلف قسمن جي ڊيٽا سان ڪم ڪرڻ لاءِ. پهرين، اسان طريقو استعمال ڪندا آهيون اسٽرنگ جي فهرست سان ۽ هڪ اسٽرنگ ان پٽ جي طور تي، ۽ پوءِ انٽيجرز ۽ انٽيجر جي فهرست سان. ڪنسول آئوٽ:

[New String, New String, New String] [888, 888, 888]
تصور ڪريو جيڪڏهن اسان وٽ عام طريقا نه آهن ۽ 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("Old String");
       System.out.println(stringBox.get());
       stringBox.set("New String");

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

       stringBox.set(12345); // Compilation error!
   }
}
اسان جو باڪس<T> ڪلاس ھڪڙو عام ڪلاس آھي. هڪ دفعو اسان هڪ ڊيٽا جو قسم ( <T> ) ٺاھڻ دوران تفويض ڪريون ٿا، اسان ھاڻي ان ۾ ٻين قسمن جون شيون رکڻ جي قابل نه آھيون. اهو مثال ۾ ڏسي سگهجي ٿو. جڏهن اسان جو اعتراض ٺاهي، اسان اشارو ڪيو ته اهو ڪم ڪندو Strings سان:
Box<String> stringBox = new Box<>();
۽ ڪوڊ جي آخري لائين ۾، جڏهن اسان 12345 نمبر کي دٻي جي اندر رکڻ جي ڪوشش ڪندا آهيون، اسان کي گڏ ڪرڻ جي غلطي ملي ٿي! اهو آسان آهي! اسان پنهنجو عام ڪلاس ٺاهيو آهي! :) ان سان گڏ اڄ جو سبق پڄاڻي تي پهتو. پر اسان عام کي الوداع نه چئي رهيا آهيون! ايندڙ سبقن ۾، اسان وڌيڪ جديد خصوصيتن جي باري ۾ ڳالهائينداسين، تنهنڪري توهان پري نه وڃو! ) جيڪو توهان سکيو ان کي مضبوط ڪرڻ لاءِ، اسان توهان کي اسان جي جاوا ڪورس مان هڪ وڊيو سبق ڏسڻ جي صلاح ڏيون ٿا
توهان جي پڙهائي ۾ بهترين ڪاميابي! :)
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION