— Salom, Amigo!
— Salom, Elli!
— Bugun biz Risha bilan senga Generics haqida hamma narsani aytib beramiz.
— Man deb o'ylagandim, men deyarli hamma narsani bilaman.
— Deyarli hamma narsani, lekin hammasi emas.
— Ha? Mayli, eshitishga tayyorman.
— Unda boshladik.
Java da Generics bu parametrlar-turlarini o'z ichiga olgan sinflar.
Genericsni paydo bo'lish sabablari – koddagi kommentariya qarang:
ArrayList stringList = new ArrayList();
stringList.add("abc"); //ro'yxatga string qo'shamiz
stringList.add("abc"); //ro'yxatga string qo'shamiz
stringList.add( 1 ); //ro'yxatga raqam qo'shamiz
for(Object o: stringList)
{
String s = (String) o; // bu yerda exception keladi, agar raqam elementiga yetib kelsak
}
Generics qanday muammoni hal qilmoqda:
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("abc"); //ro'yxatga string qo'shamiz
stringList.add("abc"); //ro'yxatga string qo'shamiz
stringList.add( 1 ); // bu yerda komplyatsiya xato chiqadi
for(Object o: stringList)
{
String s = (String) o;
}
Bunday kod shunchaki kompilyatsiyadan o'tmaydi va noto'g'ri turdagi ma'lumotlar qo'shish xatosi kompilyatsiya jarayonida aniqlanadi.
— Men buni allaqachon bilaman.
— Juda yaxshi. Takrorlash - bilimning onasi.
Java ishlab chiqaruvchilari Generics yaratishda biroz aylana yo'lni tanlashdi va tur parametrlar bilan to'liq turlarni yaratish o'rniga makrli optimizatsiya qilishga qaror qilishdi. Aslida tur parametrlariga hech qanday ma'lumot qo'shilmagan, va butun sehr kompilyatsiya jarayonida sodir bo'ldi.
List<String> strings = new ArrayList<String>();
strings.add("abc");
strings.add("abc");
strings.add( 1); // bu yerda komplyatsiya xato chiqadi
for(String s: strings)
{
System.out.println(s);
}
List strings = new ArrayList();
strings.add((String)"abc");
strings.add((String)"abc");
strings.add((String) 1); //komplyatsiya xatosi
for(String s: strings)
{
System.out.println(s);
}
— Makrli, ha.
— Ha, lekin bu yondashuvning bir salbiy ta'siri bor. Generic sinf ichida uning tur parametri haqida hech qanday ma'lumot saqlanmaydi. Bu yondashuv keyinchalik turarning yo'qolishi. deb atalgan.
Ya'ni, agar sizda tur parametrlarini o'z ichiga olgan o'z sinfingiz bo'lsa, siz ularning ma'lumotlarini sinf ichida ishlatolmaysiz.
class Zoo<T>
{
ArrayList<T> pets = new ArrayList<T>();
public T createAnimal()
{
T animal = new T();
pets.add(animal)
return animal;
}
}
class Zoo
{
ArrayList pets = new ArrayList();
public Object createAnimal()
{
Object animal = new ???();
pets.add(animal)
return animal;
}
}
Kompilyatsiya davomida barcha tur parametrlar Object ga almashtiriladi. Va sinfda tur haqida ma'lumot yo'q.
— Ha, rozi, bu unchalik yaxshi emas.
— Mayli, hammasi yomon emas, keyinchalik bu muammoni qanday hal qilishni o'rgandilar, aytib beraman.
Lekin bularning hammasi emas. Java tur-parametrlar uchun ota turini belgilash imkonini beradi. Buning uchun extends kalit so'zi qo'llaniladi. Misol:
class Zoo<T extends Cat>
{
T cat;
T getCat()
{
return cat;
}
void setCat (T cat)
{
this.cat = cat;
}
String getCatName() { return this.cat.getName(); }
}
class Zoo
{
Cat cat;
Cat getCat()
{
return cat;
}
void setCat(Cat cat)
{
this.cat = cat;
}
String getCatName() { return this.cat.getName(); }
}
Ikki faktga e'tibor bering.
Birinchidan, endi tur parametr sifatida faqat Cat turi yoki uning vorislaridan biri berilishi mumkin.
Ikkinchidan, Zoo sinfida T turidagi o'zgaruvchilarga endi Cat sinfi metodlarini chaqirish mumkin. Nima uchun - o'ng tomondagi ustunda izohlab berilgan (chunki T turi o'rniga har joyda Cat turini qo'yamiz)
— Ha. Agar biz tur parametr sifatida Cat turini yoki uning vorislarini berishimizni aytgan bo'lsak, demak T turida Cat sinfining metodlari borligiga aminmiz.
Yaxshi. Aqlli.
GO TO FULL VERSION