BÖLÜM 3
|
|
Altuğ
B. Altıntaş
|
NESNELERİN BAŞLANGIÇ DURUMU
VE TEMİZLİK
Bir nesnenin başlangıç
durumuna getirilme işlemini bir sanatçının sahneye çıkmadan evvelki yaptığı son
hazırlıklar gibi düşünebilir... Oluşturulacak olan her nesne kullanıma sunulmadan
önce bazı bilgilere ihtiyaç duyabilir veya bazı işlemlerin yapılmasına
gereksinim duyabilir. Uygulama programlarının çalışması sırasında oluşan
hataların önemli nedenlerden birisi de, nesnelerin yanlış biçimde başlangıç
durumlarına getirilmesidir; diğeri ise, temizlik işleminin doğru dürüst
yapılmamasıdır. Tasarımcı, bilmediği kütüphanelere ait nesneleri yanlış
başlangıç durumuna getirmesinden ötürü çok sıkıntılar yaşayabilir. Diğer bir
husus ise temizliktir. Temizlik işleminin doğru yapılmaması durumunda,
daha önceden oluşturulmuş ve artık kullanılmayan nesneler sistem
kaynaklarında gereksiz yer kaplarlar; ve bunun sonucunda ciddi problemler
oluşabilir. Bu bölümde nesnelere başlangıç değerleri verilmesi ve temizleme
sürecinin Java programlama dilinde nasıl yapıldığı ele alınmıştır. (yorum ekle)
Başlangıç durumuna getirme işlemlerin gerçekleştiği yer bir çeşit
yordam (method) diyebileceğiz yapılandırıcılardır (constructor); ancak, yapılandırıcılar normal yordamlardan çok farklıdırlar. Şimdi
biraz düşünelim... Elimizde öyle bir yapılandırıcı olacak ki, biz bunun
içerisinde nesnenin kullanılmasından önce gereken işlemleri yapacağız; yani,
nesneyi başlangıç durumuna getireceğiz. Ayrıca, Java bu yapılandırıcıyı, ilgili
nesneyi oluşturmadan hemen önce otomatik olarak çağırabilecek... (yorum ekle)
Diğer bir problem ise yapılandırıcının ismidir; bu isim öyle olmalıdır
ki, diğer yordam (method) isimleriyle çakışmamalıdır. Ayrıca Java’nın bu
yapılandırıcıyı otomatik olarak çağıracağı düşünülürse, isminin Java tarafından
daha önce biliniyor olması gerekir. (yorum ekle)
Bu problemlere ilk çözüm C++ dilinde bulunmuştur. Çözüm,
yapılandırıcıyla sınıf isimlerinin birebir aynı olmasıdır (büyük küçük harf dahil). Böylece Java sınıfın
yapılandırıcısını bularak, buna ait bir nesne oluşturmak için ilk adımı
atabilecektir. Küçük bir uygulama üzerinde açıklanmaya çalışırsa, bir sonraki
sayfadaki örnek verilebilir: (yorum ekle)
Örnek-3.1: YapilandirciBasitOrnek.java
(yorum ekle)
class KahveFincani { public KahveFincani() { System.out.println("KahveFincani..."); } }public class YapilandirciBasitOrnek { public static void main(String[] args) { for(int i = 0; i < 5; i++) new KahveFincani(); } } |
Yukarıda verilen örnekte art arda 5 adet KahveFincani nesnesi oluşturuluyor; dikkat edilirse, nesneler
oluşturulmadan önce (ellerimizi kahve fincanlarının üzerine götürmeden) ekrana kendilerini tanıtan
ifadeler yazdılar; yani, nesnelere ilk değerleri verilmiş oldu... (yorum ekle)
Dikkat edilmesi gereken ikinci unsursa, yapılandırıcıya (constructor) verilen isimdir; bu içinde bulunduğu sınıf ismi ile birebir
aynıdır. Anımsarsanız, normalde yordam isimleri bir fiil cümlesi içermeliydi (dosyaAc(), openFile(), dosyaOku(), readFile(), dosyaYaz(), arabaSur() vb.); ancak, yapılandırıcılar bu
kuralın da dışındadır. Yukarıda verilen uygulamanın sonucu aşağıdaki
gibi olur: (yorum ekle)
KahveFincani...KahveFincani...KahveFincani...KahveFincani...KahveFincani...
Yapılandırıcılar, yordamlar (methods) gibi parametre alabilirler:
Örnek: YapilandirciBasitOrnekVersiyon2.java
(yorum ekle)
class YeniKahveFincani { public YeniKahveFincani(int adet) { System.out.println(adet + " adet YeniKahveFincani"); } }public class YapilandirciBasitOrnekVersiyon2 { public static void main(String[] args) { for(int i = 0; i < 5; i++) new YeniKahveFincani( i ); }} |
Gönderilen parametre
sayesinde nesnenin nasıl oluşacağı belirtebilmektedir. Bu örnekte olduğu gibi YeniKahveFincani nesnesi oluşturulurken
kaç adet olacağı söylenebiliyor. Uygulamanın sonucu aşağıdaki gibi olur: (yorum ekle)
0 adet YeniKahveFincani1 adet YeniKahveFincani2 adet YeniKahveFincani3 adet YeniKahveFincani4 adet YeniKahveFincani
Yapılandırıcılar,
yordamlardaki gibi değer döndürme mekanizmasına sahip değildirler;
herhangi bir şekilde değer döndüremezler. Bu değer döndürülemez ibaresi
yordamlardaki void ifadesine karşılık gelmemektedir.
Yapılandırıcılardan çıkılmak isteniyorsa return kullanabilir. (yorum ekle)
İyi bir uygulama
yazılması her zaman için iyi bir takım çalışması gerektirir; takım çalışmasının
önemli kurallarından birisi de birinin
yazdığı kodu diğer kişilerin de kolaylıkla anlayabilmesinden geçer.
Uygulamalardaki yordam isimlerinin, yordam içerisinde yapılan işlerle uyum
göstermesi önemlidir. Bu sayede bir başka kişi sadece yordamın ismine bakarak,
bu yordam içerisinde oluşan olayları anlayabilme şansına sahip olabilir.
Örneğin elimizde bulunan müzik, resim ve metin (text)
formatındaki dosyaları açmak için yordamlar yazılmak istenirse, bunların
isimlerinin ne olması gerekir? Müzik dosyasını açan yordamın ismi muzikDosyasiAc(), resim dosyası için resimDosya-sıAc(), metin dosyasını açmak için
ise textDosyasınıAc() gibi üç ayrı yordam ismi
kullanılması ne kadar akıllıca ve pratik olur? Sonuçta işlem sadece dosya
açmaktır; dosyanın türü sadece bir ayrıntıdır. Bir ismin birçok
yordam için kullanılması (method overloading) bize bu imkanı
verebilmektedir. Aynı tür işleve sahip olan yordamların aynı isimlere sahip
olabilme özelliği, bizi isim bulma sıkıntısından da kurtarmaktadır. (yorum ekle)
Örnek-3.2: YordamOverloadingDemo1.java (yorum ekle)
class MuzikDosyasi { String m_tur = "Muzik Dosyasi" ;}class ResimDosyasi { String r_tur = "Resim Dosyasi" ;}class TextDosyasi { String t_tur = "Text Dosyasi" ;}public class YordamOverloadingDemo1 { public void dosyaAc(MuzikDosyasi md) { System.out.println( "Tur =" + md.m_tur ); } public void dosyaAc(ResimDosyasi rd) { System.out.println( "Tur =" + rd.r_tur ); } public void dosyaAc(TextDosyasi td) { System.out.println( "Tur =" + td.t_tur ); } public static void main(String[] args) { YordamOverloadingDemo1 mod1 = new YordamOverloadingDemo1(); MuzikDosyasi md = new MuzikDosyasi(); ResimDosyasi rd = new ResimDosyasi(); TextDosyasi td = new TextDosyasi(); mod1.dosyaAc(md); mod1.dosyaAc(rd); mod1.dosyaAc(td); }} |
Uygulamamızın
sonucu aşağıdaki gibi olur:
Tur =Muzik DosyasiTur =Resim DosyasiTur =Text Dosyasi
Yukarıdaki örnekte görüldüğü
gibi aynı tür işlemleri yapan yordamların isimleri aynıdır. Peki, Java aynı
isimde olan bu üç yordamı birbirinden nasıl ayırt etmektedir? (yorum ekle)
Java aynı isme sahip olan yordamları nasıl ayırt
edebilmektedir? Cevap olarak parametrelerine göre denilebilir. Konu biraz daha
açılırsa, her yordamın kendisine ait özel ve tek parametresi veya
parametre listesi olmak zorundadır. (yorum ekle)
Örnek-3.4: YordamOverloadingDemo2.java (yorum ekle)
public class YordamOverloadingDemo2 { public int toplamaYap(int a , int b){ int sonuc = a + b ; System.out.println("sonuc - 1 = " + sonuc); return sonuc ; } public void toplamaYap(int a , double b){ double sonuc = a + b ; System.out.println("sonuc - 2 = " + sonuc); } public double toplamaYap(double a , int b){ double sonuc = a + b ; System.out.println("sonuc - 3= " + sonuc); return sonuc ; } public static void main(String[] args) { YordamOverloadingDemo2 mod2 = new YordamOverloadingDemo2(); mod2.toplamaYap(3,4); mod2.toplamaYap(3,5.5); mod2.toplamaYap(6.8,4); }} |
Bu örnekte üç adet toplamaYap() yordamının parametreleri
birbirinden bir şekilde farklıdır: toplamaYap() yordamının ilki, 2 adet
temel int tipinde parametre alarak diğer adaş yordamlarından ayrılmaktadır;
geriye kalan 2 adet toplamaYap() yordamı ise aynı tip
parametreler almaktadır. Bunlar temel double tipi ve int tipi, bu iki yordamı birbirinden farklı kılan,
parametrelerin sırasıdır. Uygulamanın çıktısı aşağıdaki gibidir: (yorum ekle)
sonuc – 1 = 7sonuc - 2 = 8.5sonuc – 3= 10.8
Akıllara şöyle bir soru gelebilir: "Adaş
yordamlar dönüş tiplerine göre ayırt edilebilir mi?" İnceleyelim:
Gösterim-3.1:
void toplamaYap();double toplamaYap(); |
Elimizde 2 adet aynı isimde
ve aynı işlemi yapan, fakat biri değer döndürmeyen (void) diğeri ise double tipinde değer döndüren yordamların
olduğunu varsayalım. (yorum ekle)
Gösterim-3.2:
double y = toplamayap(); |
Gösterim-3.2 için, Java bu
yordamlardan hangisini seçeceğini tahmin edebilir; double toplamaYap()... Peki aşağıdaki gibi bir
durum için nasıl bir yol izlenmesi gerekir? (yorum ekle)
Gösterim-3.3:
toplamayap() ; |
Değer döndüren bir yordamı döndürdüğü tipe karşılık gelen değişkene
atama zorunluluğu
olmadığı hatırlatalım. Kısacası bu koşulda Java hangi yordamı çağıracağını
bilemeyecektir. Bu nedenle, Java dilinde dönüş tiplerine göre yordamların ayırt
edilmesi kabul görmez; ayırt edilmesini sağlayan tek şey parametrelerindeki
farklılıktır. (yorum ekle)
Eğer uygulamaya herhangi bir
yapılandırıcı koyulmazsa, Java bu işlemi kendiliğinden yapmaktadır. Varsayılan
yapılandırıcılar aynı zamanda parametresiz yapılandırıcılar (default
constructor veya "no-args"
constructor) olarak ta
anılmaktadır; bunları içi boş yordamlar
olarak düşünebilirsiniz. (yorum ekle)
Örnek-3.5: VarsayilanYapilandirici.java
(yorum ekle)
class Kedi { int i;}public class VarsayilanYapilandirici { public static void main(String[] args) {Kedi kd = new Kedi(); //Varsayılan yapılandırıcı çağrıldı }} |
Java’nın yerleştirmiş olduğu
varsayılan yapılandırıcı açık bir şekilde gözükmemektedir. Açık şekilde görmek
istenirse; (yorum ekle)
Örnek-3.6: VarsayilanYapilandirici.java
(değişik bir versiyon) (yorum ekle)
class Kedi { int i; /* varsayılan yapılandırıcı bu yapılandırıcıyı eğer biz koymasaydık Java bizim yerimize zaten koyardı */ public Kedi() {}}public class VarsayilanYapilandirici { public static void main(String[] args) {Kedi kd = new Kedi(); //Varsayılan yapılandırıcı çağrıldı }} |
Eğer, yapılandırıcı kodu
yazan kişi tarafından konulursa, Java varsayılan yapılandırıcı desteğini
çekecektir. Bunun nedeni şöyledir: Eğer bir sınıfa ait herhangi bir
yapılandırıcı belirtilmezse, Java devreye girip kendiliğinden varsayılan bir
yapılandırıcı koyar; eğer, biz kendimize
ait özel yapılandırıcılar tanımlarsak, şöyle demiş oluruz: "Ben ne
yaptığımı biliyorum, lütfen karışma". Bu durumda olası tüm yapılandırıcılar
bizim tarafımızdan yazılması gerekir. Şöyle ki: (yorum ekle)
Örnek-3.7: VarsayilanYapilandiriciVersiyon2.java
(yorum ekle)
class Araba { int kapi_sayisi; int vites_sayisi ; public Araba(int adet) { kapi_sayisi = adet ; } public Araba(int adet, int sayi) { kapi_sayisi = adet ; vites_sayisi = sayi ; }}public class VarsayilanYapilandiriciVersiyon2 { public static void main(String[] args) {Araba ar = new Araba(); // ! Hata var! Bu satır anlamlı değil; yapılandırıcısı yok Araba ar1 = new Araba(2); Araba ar2 = new Araba(4,5); }} |