Generics?
Aslında konunun başlığı genel anlamda konuyu özetliyor (en azından sadece bir kısmını :)). Java 1.5 versiyonuyla gelen
Generics özelliği, yazdığımız sınıfı tipler üzerinde soyutlaştırmamızı, türden bağımsız sınıflar yaratabilmemizi sağlıyor. Yani, sınıfı yazarken sınıfın metotlarının birden fazla tip için çalışabilirliğini sağlamış oluyoruz. En güzel anlatım örnekle anlatımdır diyerek (tamamen kendi görüşüm :)) bir örnek üzerinde gösterelim. Örneğin,
ArrayList sınıfı. Aslında 1.2 versiyonundan beri
Generics özelliğinden mahrum olarak Java'da mevcut bir sınıf. İçerisinde tüm nesneleri tutabilen bir liste. İçerisinden istenilen tipi barındırabilmek ilk bakışta çok cazip gelse de aslında çok sakat(!) bir işlem. Bu konuya daha sonra değineceğim. Burada sadece örnek veriyorum.
Apple anApple = new Apple(); Pear aPear = new Pear(); ArrayList ourBag = new ArrayList(); ourBag.add(anApple); ourBag.add(aPear);
Görüldüğü üzere elma ile armutu bir araya koyduk.
ArrayList sınıfının eski halinde add metodu
Object tipinde parametreye sahip olduğu için iki nesneyi de ekleyebildik.
add (Object o);
Şimdi de kendimizi biraz kısıtlayalım.
Generics özelliğini kullanalım.
ArrayList<Apple> ourAppleBag = new ArrayList<Apple>(); ourAppleBag .add(anApple); ourAppleBag .add(aPear); // Dikkat: derleyici izin vermez.
Oops.
ArrayList'in yanında
Apple nesnesi var. Artık çantamıza sadece elma atabilir hale geldik (3. satıra derleyici izin vermeyecektir). Eğer, armutlarımızı tutmak istiyorsak yeni bir çanta almamız lazım.
ArrayList<Pear> ourPearBag = new ArrayList<Pear>();
Peki ne oldu? Neden birden kısıtladık kendimizi? Ayrıca türden bağımsızlık işin neresinde? Metodun parametresini
Object türünde yaparsak tüm tipteki nesneleri alabilir değil mi artık?
Nimetler, Nimetler, Nimetler
Öncelikle elmayla armut aynı çantada olursa neler olur onu görelim. Parametre olarak bir
ArrayList alan metodumuz olduğunu düşünelim.
getAppleJuice (ourBag); // ... public void getAppleJuice(ArrayList bag) { Apple anApple = bag.get(0); }
Bu metodu derlemek istediğinizde derleyici hata vererek sizden cast işlemi yapmanızı isteyecektir. Çünkü;
Object get (int index);
get metodu
Object tipinde bir nesne döndürüyor.
getAppleJuice (ourBag); // ... public void getAppleJuice(ArrayList bag) { Apple anApple = (Apple) bag.get(0); }
Artık derleyici bize kızmıyor. Ama her zaman içinde elma olduğunu nereden bileceğiz. Şu durumu düşünelim;
getAppleJuice (ourBag); // ... public void getAppleJuice(ArrayList bag) { Apple anApple = (Apple) bag.get(1); }
Derleyici için bir sorun yok. Programı çalıştırabilirsiniz. Hatta müşterinize satabilirsiniz. Bir süre sonra müşteriniz size elma suyu yerine armut suyu içtiğini, programın bozuk olduğunu söylerse şaşırmayın. Gerçekte olan ise, programın çalışması anında Java bize kızar ve bir exception fırlatır. Buyrun size en güzelinden bir böcek. E o zaman
ArrayList sınıfına müdahele edelim ve
Object olan yerleri
Apple'a çevirelim. Artık,
getAppleJuice metodunun elma suyu döndürmesini garantilemiş olduk. Peki armutları tutmak için ne yapacağız?
ArrayList sınıfını kopyalayacağız ve tüm
Object olanları
Pear yapacağız. Meyveler arttıkça kopya sınıflar da artmış oldu. Yeni her tip için sınıfı tekrar yazacağız. Bu dertten kurtulmak gerekir. Bir kere yazalım hepsi için program anında bile düzgün çalışsın. Üstelik sadece 1 sınıfla!
Generics ile yazılmış
ArrayList sınıfı
ArrayList<E> şeklinde tanımlanıyor. Artık nesnesini oluştururken hangi sınıfı verirsek çantaya o nesneyi atabileceğiz. Yeni
add metodu;
add (E e);
şeklinde. Artık parametre çanta yaratırken belirttiğimiz
E tipinde.
ArrayList<Apple> ourAppleBag = new ArrayList<Apple>(); ourAppleBag.add(anApple);
Artık, çantamız bir elma çantası ve armut almıyor. Armut alan çanta için armut çantası yaratacağız. Şimdi elma suyu metodumuza yeniden bakalım;
getAppleJuice (ourAppleBag); // ... public void getAppleJuice(ArrayList<Apple> bag) { Apple anApple = bag.get(1); }
Biraz kısıtladık kendimizi değil mi? Ama program çalışırken ortaya çıkacak sürprizlerden kurtarmış olduk kendimizi. Artık metod aldığı çantanın bir elma çantası olduğunu biliyor. Cast işlemine de ihtiyaç duymuyor.
Sonuç?
Bu tarz her yazımda olduğu gibi yazının sonunda öneride bulunayım:
- Halihazırdaki Java sınıflarını (özellikle ArrayList gibi Collection türündeki sınıfları) kullanırken Generics halini kullanın. Hatta diğer hali hiç kullanmayın :)
- Eğer, kendi yazdığınız sınıf birden fazla tip için çalışacaksa tek ve doğru yolunuz Generics şeklinde yazmak.
Devamı için :
Java Generics - Tipler Üzerinde Soyutlaşma
Hiç yorum yok:
Yorum Gönder
Yorumunuzu esirgemeyiniz..