Java’ya Nasıl Başlarım? Java’yı Nasıl Öğrenirim? – IV

Bu serinin 4. yazısında, son yazıda gelinen noktadan, tekrar kullanım bölümü ile devam edebiliriz. Tekrar kullanımdan kasıt, var olan nesnelerden yeni nesneler oluşturmaktır. Bunu yapmanın ise temelde iki yolu vardır: bileşim ve kalıtım ya da miras. Bileşim (composition), var olan sınıfların tipinden nesne değişkenlerine sahip olacak şekilde yeni bir sınıf oluşturmaktır. Bu kullanıma sahip-olma ya da has-a ilişkisi denir. Miras ise bir benzerlik ilişkisidir ve is-a olarak adlandırılır. Bu bölüme, bileşim ile başlar sonra da mirasa geçerim ve detaylıca ele alırım. Tabi ki miras alan sınıfta, ebeveyndeki metodun tekrar tanımlanması yani overriding bu kısımdaki en önemli konulardandır. Sonrasında ise java.lang.Object sınıfıni ve APIsini incelerim ve örneklerle neden toString() ya da hashCode() ve equals() gibi metotların yeniden tanımlanması gerektiğini anlatırım. Doğal olarak başlatma sırası (order of initialization) ve final anahtar kelimesinin ilgili kullanımları da bu konunun alt başlıkları arasındadır.

Sonrasında, miras ve yeniden tanımlama üzerine kurgulanan ve nesne-merkezli dillerin en önemli özelliği olan çok şekillilik yani polymorphism gelir. Cok şekilliliğe önce yukarı atama (upcasting) ile başlarım ve bir referansın, zamanın farklı anlarında, kendi tipi ve alt tiplerinden olan nesneleri gösterebileceğini anlatıp, dinamik metot çağrısına geçerim. Daha sonra ise aşağı atama ya da downcasting gelir ve sonuçta instanceof operatörü ele alınır. Bu sırada, referansın arayüzü ile nesnenin arayüzü arasındaki ayırım hep vurgulanır.

Sonra ise sıra soyut sınıflar (abstract classes) ve arayüzlere (interfaces) gelir. Soyut sınıflar, şu ana kadar sınıflar ile nesne-merkezli programlamada gelinen noktayı bir adım öteye taşır. Söyleki: Java eğitimlerinde bu ana kadar sıklıkla, arayüz-gerçekleştirme ya da interface-implementation ayırımından bahsederim. Nesne-merkezli programlamaya giriş yaptığım bölümden, erişim niteleyicileri ele aladığım kısıma kadar, özellikle de düşük bağımlılıklı (lowly-coupled) ve yüksek iç-bütünlüklü (highly-cohesive) yapılar ve sınıflardan bahsederken, devamlı arayüz ve gerçekleştirme kavramları ile aralarındaki ilişkiyi vurgularım. Bu iki kavram, soyut sınıflar ve arayüzler konularında, çok daha geniş ve pek çok pratik uygulamayla o şekilde ele alınır ki her yönüyle ele alır, güzek örneklerle açıklarım. Bu güzel örnekler arasında decorator ve proxy tasarım desenleri de yer alır.

Soyut sınıflar ve arayüzler ile Java’nın en temel nesne merkezli yapıları ele alınmış olur. Artık sıra bir diğer çekirdek dil yapısı olan sıra dışı durumlara (exceptions) gelmiştir. Sıra dışı durumları ele alırken, sadece try-catch-finally blokları ve throw ve throws anahtar kelimelerini ele almam, neden sıra dışı durumları yönetmeliyiz, hatta ihtiyaç analizi sürecinde sıra dışı durumlar nasıl bulunurdan başlayarak, tasarımda nasıl yer aldıklarından bahsederek, kodlama anına kadar gelirim. Bu kısımda ayrıca assert anahtar kelimesini ve ‘Assertion-driven Desing” (ADD) yaklasımından da bahsederim.

Bir sonraki bölümde torbaları ele alırım. Collection arayüzünden başlayıp, Set ve List arayüzleri ile devam ederim. Sonuçta, HashSet, TreeSet, ArrayList ve LinkedList ile ilgili örnekler verip, ne zaman hangisini kullanmalıyızı ele alırım. Orneğin Set’in, nasıl aynı nesneden iki tane eklenmesine izin vermediğini ya da sona ekleme yapılmayıp başa ve ortalara ekleme yapıldığında neden LinkedList kullanmamız gerektiğini örneklerle gösteririm. Daha sonra Map arayüzüne geçerim ve gerçekleştirmeleri olan HashMap ve TreeMap’i benzer şeklide ele alırım. Sonrasında, java.util paketindeki bu torbaları kullanarak yeni veri yapıları ve torbaları nasıl oluşturabilirizi bir iki örnek ile katılımcılarla tartışırım. Java SE’de var olan torbalar yeterli olmadığında, Apache Commons’in Collection projesinde var olan yapıların imdadımıza nasıl yetiştiğinden bahsseder, oradaki veri yapıları ve torbalardan örnekler veririm. 

Torbalar bölümünün en zevkli tarafı ise bence her zaman şudur: Arayüzlerin kullanımına nefis örnekler sunması ve arayüz-gerçekleştirme ayırımını güzel bir şekilde vurgulanması. Katılımcılara Collection arayüzünden hiç bahsetmeden, “hadi bir torbayı modelleyelim” deyip, Torba isimli bir arayüz oluşturup sonra da mesela “ekle” davranışını gerçekleştirirken, ekleme sırası gözetip gözetmeyeceğimiz ya da sıralama yapıp yapmayacağımız, ya da ne bileyim örneğin, aynı nesneden birden fazla eklemeye izin verip vermeyeceğimiz gibi detayların, nasıl birer gerçekleştirme konusu olduğunu açıklarım. Zaten bu kısımdaki TreeSet ya da TreeMap gibi yapıları kullanırken nesnelerimizin, istediğimiz kriterlere göre sıralanabilmesini sağlamak amacıyla kullandığımız, Comparable ve Comparator arayüzleri, nesnelerimize nasıl farklı yetkinlikler kazandıracağımızın en güzel örneklerindendir.

Torbalar bölümünde ayrıca java.util.Collections sınıfı üzerindeki algoritmalardan da bahsedip, arama, sıralama, kaydırma vb. işlemlerinden örnekler veririm.

Bu bölümün en son konusu ise generics ya da  “bir tipe özel” yapılardır. Generics, iç sınıflar (inner classes) gibi anlaşılması zor ya da zordan öte tecrübe isteyen konulardandır. Dolayısıyla, generic yapıların, öncelikle bir tipe özel torbalar oluşturmak için nasıl kullanılacağından bahsederim. Sonrasında sadece ufuk açmak ya da meraklı zihinlere bir tiyo vermek amacıyla şablon sınıflardan bahsedip, bir kaç örnek veririm. Hatta Java API’sine gidip, örneğin java.util.Collections sınıfının binarySearch(List<? extends Comparable<? super T>> list, T key) metodunun arayüzünün nasıl anlaşılması gerektiğini anlatırım 🙂

Artık sıra giriş/çıkış (I/O), çok kanallı programlama (multi-threading) ve veri tabanı programlaması (JDBC) gibi konulara gelmiştir. Bunları da bir sonraki yazıda ele alalım.

Bol Java’lı günler dilerim 🙂

 

Toplam görüntülenme sayısı: 4903