 |
Pazar sabahları ne yaparsınız? Peki bir
bilgisayar programcısı olsanız ne yaparsınız? Muhtemelen, cumartesi
gecesinin sabaha kadar süren çalışmalarından başınızı kaldıramadığınız için,
bütün gün uyumak isteyebilirsiniz. Ben çoğunlukla ve düzenli olarak,
İstanbul Bostancı sahilinde çok erken saatlerde yürüyüş yaparım. Sabah 6
ile 7 arası inanılmaz bir huzur bulurum burada. Bir yandan denizden gelen
tertemiz iyotlu hava, diğer yandan sessizlik, martı seslerinin ahengi ve göz
kamaştırıcı güzelliği ile İstanbul boğazının Marmara denizi ile
kucaklaşması. Matematikçi olmamın bana verdiği kazanımlardan birisi, etrafta
olup bitenleri son derece felsefik inceleyebilme yeteneği. Sizde bilirsiniz
ki tarihin en ünlü matematikçileri mantık, sosyoloji, felsefe, psikoloji
gibi bilimlerle hep yakından ilgilenmişlerdir. Onlardan birisi olmayı çok
isterdim gerçekten. |
Herşeyden önce bir programcı pek çok zorlukla,
hayatta karşılaştığından çok, programlarını yazarken karşılaşır. O nedenle,
sağlıklı ve ruhsal açıdan huzurlu bir beden, onun bu zorlukları aşmasında en
büyük yardımcıdır. Ben bu yürüyüşleri çoğunlukla kafamı boşaltmak, kendi
dünyamda huzur bulmak ve gözümden kaçan ayrıntıları daha sağlıklı inceleyebilmek
amacıyla yaparım. İşte bu sabahta o amaçla yapılan bir yürüyüşteyim.
Adımlarımı attıkça, ciğerlerime dolan nefis iyotlu
deniz havası daha sağlıklı düşünmemide sağlıyor. Etrafıma baktığımda, her türden
nesneyi daha berrak sezinleyebiliyorum. Nesne! O o! Bu lafı bana kim söyletti?
Nesne...Nesne...Gerçekten de şöyle bir durdum ve etrafıma bakındım. Her yerim ,
ben de dahil olmak üzere nesnelerden oluşmaktaydı. Evrenin sahip olduğu gizemi
ve mükemmelliği kimse inkar etmez. Çağımız boyunca ve gelecektede pek çok
teknolojik, endüstüriyel, matematik yaklaşıma ilham kaynağı olmuş sistematikler
içerir. Bu düşünceler ile tekrar yürümeye başladığımda, nasıl olduysa bir anda
kendimi bilgisayar dillerinin gelişimini düşünürken buluverdim. Basic, pascal,
C, Fortran vesaire... Sonra tekrar durdum. Aklıma C++,Java,C# gelivermişti
birden bire. Hepside nesneler ile uğraşan, nesneler üzerine kurulu yapılara
sahipti. Hepside Nesneye Dayalı Programlama dillerindendi.
Nesne kavramını, günümüz modern programlama
dillerine kim yerleştirmiş ise eminimki benim gibi bir yürüyüş sırasında bunu
yapmıştır diye düşünüyordum. Bir anda kendimi Yazılım Mimarları gibi düşünürken,
ayağımı yere sürtüp tepe taklak tabir yerinde ise iki seksen yere uzandım.
Allahın tokatı yoktur derler. Neyseki kendime gelmiştim. O adamların tırnağı
bile olmak büyük bir onur olurdu sanırım. Evet sonuç itibariyle sabahları bu
kadar erken yürümemin nedeni buydu. Tökezleyip düştüğümde etrafta kimsenin
olmayışı...Sonuç itibariyle geriye dönüp baktığımda, hem programlama dillerinin
nesneye dayalı hale gelmesi ile, yaşamımızın ekosistemini örnek alarak ne kadar
büyük üstünlükler sağladığını düşünüyor, bir yandanda ne kadar uzağa yürümüşüm
şimdi nasıl geriye dönecem diye veryansın ediyordum. Aklıma her zaman olduğu
gibi parlak bir fikir geldi. Dönüşte çevremdeki nesnelerin programlama
dillerindeki etkilerini düşünecektim.
Çevremizde ne kadar çok nesne var. Çiçekler,
böcekler, insanlar, arabalar, otobüsler, kuşlar, taşlar, kayalar...Bu liste o
kadar kabarıkki saymaya kalkmak bile sonsuzlukla çarpışmak gibi bir şey olsa
gerek. Her nesnenin belli bir takım özellikleri, işlevsellikleri ve hatta
amaçları var. Bazı nesneler bir araya gelerek başka yeni nesnelerin doğmasına
neden olurlarken onlara bir takım ortak özelliklerinide veriyorlar. Aynı
insanların bir araya gelerek evlenmesi, çocuk sahibi olması ve çocuklarına kendi
özelliklerinden bir takım kalıtımlar bırakması gibi. Bazı nesneler kendi içinde
kapalı, sahip olduğu değerleri değiştirilemeyen ama gözlemlenebilen türden. Bazı
nesneler ufak değişikliklere uğrayarak başka nesnelere ilham kaynağı olmuşlar.
Bu çeşitlilik altındaki tüm neselerin ortak özelliklerini bir arada düşünmek ve
bir kenara koymak onları bu ortak niteliklerine göre sınıflandırmaktan başka bir
şey değil.
Otomobilleri bir sınıf altında düşünebiliriz. Her
otomobil 4 tekerlekli, motoru olan, ileri geri hareket edebilen, direksiyona
sahip ve benzinle çalışan, gaza basıldığında viteste ise hareket eden, frene
basıldığında duran ve bunlar gibi pek çok ortak özelliğe ve işleve sahip olan
birer nesne. Ama bu sınıfa ait tüm nesneler bir birlerinden farklı olabileceği
gibi birbirlerinin aynısıda olabilir. Otomobil firmalarının arabalarını
düşündüğümüzde, hepsinin farklı özelliklere sahip ama temel işlevsellikleri
neredeyse aynı olan nesneler olduklarını söyleyebiliriz. Hatta üretim hattından
yeni çıkmış tüm gri renkli opel vectra 1.6'lar motor seri numaraları hariç
birbirlerinin aynısı olan nesnelerden oluşan bir nesne koleksiyonundan başka bir
şey değildir.
İşte gerçek hayattaki nesnelerin bizler için
anlamı ve önemi neyse, nesneye dayalı bir programlama dili içinde nesnelerin
anlamı o derece önemlidir. Herşeyden önce, bu dillerde bütün kavramlar,
nesnelere ve dolayısıyla bu nesneleri oluşturmak yada örneklemek için kullanılan
sınıflara bağlıdır. Düşünün ki object sınıfı değilmidir C# dilinde ve hatta
Java'da en üst sınıf. Java programlama dilide tam anlamıyla nesneye dayalı bir
dil. Dolayısıyla nesneleri kullanan bir dil. Nesneleri, sahip oldukları
özellikleri, değerleri ve işlevleri ile kullanan bir dil. Bu düşünceler
eşliğinde geri
dönüş yolunu tamamladım. Artık eve dönme vaktim gelmişti. Şu andan sonra
yapılacak en güzel şey, eve gitmek sıcak bir duş almak ve Pazar sabahının
gazetelerini okuyup güne merhaba demekti. Ama ne yazıkki böyle olmamıştı.
İçimdeki korkunç öğrenme açlığı, gazete yerine Java ile ilgili kaynakları
araştırmama neden oldu. Ama her zaman olduğu gibi yanımda sıcak bir kahvem
vardı.
Uzun süre camdan dışarı bakarak sınıfların yerini
düşündüm ve onları daha iyi anlamaya çalıştım. Gerçektende Javada'da diğer
nesneye dayalı programlama dillerinde olduğu gibi herşey sınıflar üzerine kurulu
idi. Dolayısıyla sınıfları çok iyi kavramak programlama dilini öğrenirken
yaşadığım süreçte çok ama çok önemliydi. Önemli olan sadece sınıfların nasıl
yazıldığını öğrenmek neleri ihtiva edeceğini bilmek değildi. Sınıfları en uygun
şekilde, en etkin ve verimli şekilde kullanabilmekte çok önemliydi. Söz gelimi,
bu gün .net dilinde, veritabanlarındaki veriler ile çalışmak için inanılmaz
kabiliyetli ve yetenekli sınıflar vardı. Java içinde bunların benzerlerini
yazmak istememiz bu tip sınıfları tasarlamamız anlamına geliyordu. Veya
veritabanlarından okuduğumuz veri satırlarını düşünelim. Bunları birer sınıf
nesnesi olarak uygulamamıza yerleştirmek , işlemlerimizi dahada
kolaylaştırmazmıydı. Veritabanına bağlanır istediğimiz satıra ait verileri uygun
bir sınıf nesnesine aktarır ve bunları tekrar veritabanına gönderinceye kadar
bağlı olmak zorunda kalmazdık. Aynı DataSet kavramı gibi. Ama daha sade, daha
kolay ve belkide daha etkili.
Elbette Java dilinde veritabanları ile ilgili ne
tür işlemler yapabileceğimi ne tür kabiliyetlere sahip olduğumu şu an için
bilmiyorum ama ileride bunları öğrenmek içinde can atıyorum. Ama şu an için
yapacağım sınıfların nasıl oluşturulduğunu ve kullanıldığını anlamak olucak.
Java dilini öğrenmeye devam ettikçe sanıyorumki sınıf kavramını çok daha iyi
kavrayacağım. Gerçi, bu kavrama C# dilinden oldukça aşine ve hakimim. Ama Sun'ın
belkide bilmediğim sürprizleri vardır bu konuda. Neyse deneyip göreceğiz.
Normalde kendimce bu kadar çok konuşmam. Aslında daha az söz ve daha çok hareket
taraftarıyımdır. Eeee atalırımız ne demiş; nerde hareket orda bereket. Tipik bir uygulamacı işte. O bakımdan makinemin başına geçip
ilk sınıfımı yazsam iyi olucak sanırım.
Şimdi bir uygulama geliştirmek istiyorum. Bu
uygulama hayali olarak bir tablodan bir kaç satır veri alsın istiyorum ve sonra
bu verileri birer nesneye aktarmak istiyorum. Bu amaçla öncelikle kafamda hayali
bir tablo tasarladım ve sonrada bu tablonun satırlarını birer sınıf nesnesi
olarak nasıl tasarlayabileceğimi düşündüm. Aslında işin tasarım kısmında hep bir
şeyler çizmek, düşünceleri kağıda dökmek en güzelidir sanırım. Bunun için aslında
çok güzel bir yapı var. UML. Fakat ben buradaki şekilleri ezberlemekten ve
unutmaktan bıktım. O nedenle başka birisine şeklimi göstermediğim sürece genelde
kendi kafamda oluşturduğum çizelgeleri kullanırım. Sanırım buna ben BML
diyeceğim. Diğer yandan çizdiklerimin başkaları tarafından kolayca anlaşılması
içinde dikkat ediyorum.

Aslında yapmak istediğim şey çok basit. Tablodaki
satırları alıp, Sınıf nesneleri haline getirmek. Bunu yaparken, tablodaki
alanların değerlerini, sınıfım içinde oluşturacağım değişkenlerde saklıyacağım.
Bu durumda, sınıfımdan nesneler türettikten sonra, içindeki değişkenlere değer
atamamı sağlıyacak işlevlere ihtiyacım olucak. Ayrıca program içinde, bir
nesneye ait bu alan değerlerini değiştirmek isteyebilirim. Bunun içinde bir veya
bir kaç metoda ihtiyacım olabilir. Artık ne yapmak istediğimi bildiğime göre
kodları yazmaya başlamanın zamanı geldi. Ne yazıkki yine sıkıcı Notepad
editorümüze döneceğiz. Aslında buna bir çare bulmam lazım. Java programlarını
yazabileceğim ücretsiz bir yazılıma ihtiyacım var. Aslında kaynaklarımdan en iyi
java editörünün Borland firmasının JBuilder ürünü olduğunu öğrenmiş
bulunmaktayım. Üstelik bu ürünün Personel sürmüde ücretsiz olarak
dağıtılıyormuş. Sanıyorum bu öğleden sonra vaktimi ayırıp bu sürümü internetten
indirmek için kullanabilirim. Ama şimdilik notepad ile devam edeceğim.
Evet öncelikle bana, oluşturacağım nesneleri
örneklendireceğim bir sınıf lazım. Zaten Java'yı öğrenmeye başladığımdan beri,
mutlaka sınıf tanımlamalarını yapıyoruz, nitekim Java dilide diğer nesne
yönelimli diller gibi, nesnelere dolayısıyla sınıflara dayanıyor. O halde ne
duruyoruz. İşe sınıfımız oluşturmakla başlayalım.
public class SinifKisi
{
} |
Elbette sınıfı böylesine tanımlamak son derece
anlamsız ama birazdan sınıfın içine koyacağımız üyeler ile bayağı bir yol
katedeceğiz. Biz oluşturduğumuz bu sınıfta türeteceğimiz nesneler ile,
tablomuzdaki satırları temsil ediceksek eğer, tablodaki alanlarıda temsil
etmemiz gerekir. İşte bunun için sınıfımız içerisinde, tablodaki alanlara denk
gelicek alanlar tanımlayacağız. Bu alanların özel yanı private olarak
tanımlanacak olmaları. Bunun sebebi, her zamanki gibi kapsülleme
(Encapsulating). Kapsüllleme sayesinde, sınıfımız içinde kullandığımız alanların
dışarıdan her hangibir etki ile doğrudan değiştirilemelerini engellemiş
oluyoruz. Bu durum bizim isteğimiz dışında oluşabilecek atamaların önüne
geçmemize ve illede bu alanların değerleri değişecekse bizim belirlediğimiz bir
çizgide olmasına neden oluyor. Bu da programcılıkta ve özellikle nesne yönelimli
programlamada çok büyük bir yere sahip olan Kontrol'ün elimizde olmasını
sağlıyor.
Aslında kapsüllemeyi , içtiğimiz kapsül şeklindeki
ilaçlardan yola çıkarak daha iyi anlayabiliriz. Çoğu zaman kapsül şeklinde
ilaçlar içeriz. Bu ilaçların dışındaki koruyucu kapsül içinde, binlerce belkide
onbinlerce zerrecik yer alır. Bu zerreciklerin böyle bir kapsül içine
alınmasındaki en büyük neden bir arada tutulmak istenmeleri olarak
düşünülebilir. Aynı sınıflarımızda kullanacağımız alanları bir arada tutmamız
gibi. Diğer yandan, kapsüllenmelerinin en büyük nedeni, istenilen hedefe kadar
gidilecek yol üzerinde (ağız, tükürük bezleri, yemek borusu, mide vesaire...)
karşılaşılabilecek ve zerrelerin istenmeyen şekilde vücuda karışmasına neden
olucak etkilerden korunmaktır. Amaç ilacın istenen yerde kapsülünün istenen etki
ile eriyerek, zerreciklerin serbest kalmasıdır. Elbetteki kapsül ilaç örneği
sınıflardaki kapsüllemeyi tam olarak açıklayamaz, ancak çok büyük benzerlikler
taşır.
İşte sınıflarımızı yazarken de, bu sınıflar
içierisinde tanımlanan ve sınıfa ait nesneler tarafından erişilebilen alanların,
bizim programladığımız etkiler dışında değiştirilmesini istemeyiz. Bir alanın
sadece okunabilir olmasını veya, bu alandaki değerlerin bizim kontrolümüz
altındaki metodlar ile değiştirilmesini isteyebiliriz. İşte bu uyumu sağlamak
için, nesneler tarafından kullanılan ve sınıf içinde tanımlanan alanları private
olarak belirtiriz. Böylece bu alanlara sadece tanımlanmış oldukları sınıf
içerisinden erişilebilecektir. Şimdi uygulamamızda, tablo alanlarını temsil
edicek sınıf içi özel alanlarımızı oluşturalım.
public class SinifKisi
{
private int fID;
private String fAd;
private String fSoyad;
private String fTelefon;
} |
Şimdi C# ile bu sınıfı yazıyor olsaydım bu alanlar
için birer özellik tanımlar ve get ile set bloklarını oluşturudum. Ancak
kaynaklarıma baktığımda şaşırtıcı bir şekilde bu tarz ifadelerin, yani get ve set
bloğu olan tarzda özelliklerin yer almadığını gördüm. Belki bu gözümden kaçmıştı
ama tekrar baktığımda iyice emin oldum. Özellik tanımlamaları yerine,
özelliklerinin rollerini üstlenecek olan metodları kendimiz yazıyorduk. Aslında
bu tuhafıma gitti. Neyse yapacak bir şey yoktu, yeni bir fincan kahve almaktan
başka. İşe koyulma vakti. Herşeyden önce bu alanların değerlerinin
değiştirilebilmesini istiyorum aynı zamanda değerlerinin okunabilmesinide. O
zaman her biri için birer metod yazmam gerekiyor.
public class SinifKisi
{
private int fID;
private String fAd;
private String fSoyad;
private String fTelefon;
public int getID()
{
return fID;
}
public String getAd()
{
return fAd;
}
public String getSoyad()
{
return fSoyad;
}
public String getTelefon()
{
return fTelefon;
}
} |
Önce alanların değerlerini sınıf örnekleri olan
nesneler üzerinden okuyabilmek için, her bir alan için bir metod yazdım. Bu
metodların tek yaptığı return anahtar kelimesi ile geriye, private sınıf
alanlarının değerlerini göndermek. Tabi burada önemli olan nokta, bu metodların
dönüş değerlerinin, private alanların veri tipleri ile aynı olmaları. Bununla
birlikte bu metodları, sınıf dışından kullanabilmek için yada bu sınıfımızdan
türeteceğimiz nesnelerde kullanabilmek için public belirteci ile tanımlıyoruz.
Sıra geldi bu alanların değerlerini değiştirecek metodlara. Herşeyden önce, fID
alanımız aslında, tablomuzdaki ID isimli birincil anahtar alanını işaret ediyor.
Tablomuzun bu değerinin kullanıcı tarafından değiştirilmesi kesinlikle
istenmeyecek bir durum. Ancak diğer yandan bu alana ait değerleri okumak
isteyeceğimiz, örneğin where sorgularında kullanmak isteyeceğimiz durumlarda
olucak. İşte kapsüllme için bir neden daha.
public class SinifKisi
{
private int fID;
private String fAd;
private String fSoyad;
private String fTelefon;
public int getID()
{
return fID;
}
public String getAd()
{
return fAd;
}
public void setAd(String ad)
{
fAd=ad;
}
public String getSoyad()
{
return fSoyad;
}
public void setSoyad(String soyad)
{
fSoyad=soyad;
}
public String getTelefon()
{
return fTelefon;
}
public void setTelefon(String telefon)
{
fTelefon=telefon;
}
} |
Artık bir yerler gelmeye başladık. Ancak
sınıfımızda halen daha eksik üyeler var. Herşeyden önce, bir nesneyi yaratmanın
en temel yolu new anahtar kelimesini kullanmak. Bu anahtar kelime, tanımlandığı
sınıf için bir yapıcı metod çağırır. Yapıcı metodlar, çoğunlukla sınıf örneği
olan nesneleri ilk kullanıma hazırlarken kullanılır. Örneğin, sınıf içinde
kullanılan alanlara başlangıç değerlerinin verilmesi ve benzeri işlemler için.
Bir sınıf için birden fazla yapılandırıcı tanımlayabiliriz. Bu, yapılandırıcı
metodların aşırı yüklenmesi ile mümkün olur. Aşırı yükleme bildiğiniz gibi, bir
metodun aynı isim altında farklı işlevler için kullanılmasıdır. Burada aynı
isimli bu metodları birbirinden ayıran, kullanılan parametrelerin
farklılıklarıdır. C# dilinde olduğu gibi aşırı yüklü metodların ayrı şekilde
algılanmaları hem metod parametrelerine hemde metodun dönüş tipine bağlıdır.
Oysa Java'da durum farklıdır. Java'da aşırı yüklü metodlar sadece parametreleri
ile ayırt edilebilir, metodların dönüş tiplerinin, metodların ayırt edilmesinde
bir etkisi yoktur. Sınıfımızı geliştirmeye devam etmeden önce aşırı yüklü
yapılandırıcıların bir sınıf içinde nasıl kullanıldığına dair bir örnek verelim.
public class OverloadM
{
private int deger1;
private int deger2;
public OverloadM()
{
deger1=10;
deger2=15;
}
public OverloadM(int d1,int d2)
{
deger1=d1;
deger2=d2;
}
public OverloadM(int d1)
{
deger1=d1;
}
public void Yaz()
{
System.out.println("Deger1:"+deger1+"
Deger2:"+deger2);
}
} |
Burada OverloadM isimli sınıfımızda, üç adet
yapılandırıcı metod yer almaktadır. Bunları kullanacak olan sınıfımız ise
Program sınıfımız olup kodları aşağıdaki gibi olucaktır.
public class Program
{
public static void main(String[] args)
{
OverloadM birinciNesne=new
OverloadM();
birinciNesne.Yaz();
OverloadM ikinciNesne=new
OverloadM(18,24);
ikinciNesne.Yaz();
OverloadM ucuncuNesne=new
OverloadM(45);
ucuncuNesne.Yaz();
}
} |
Bu iki sınıfı başarı ile derledikten sonra,
Program.java isimli uygulamayı çalıştırdım. Sonuç aşağıdaki gibi oldu.

Görüldüğü gibi yapıcı metodlarımızda dikkat çeken
ilk özellik, sınıf adı ile aynı olmaları. Ancak burada karşılaştığım ilginç bir
durum oldu. Yapıcı metodların nasıl kullanıldığı ile uğraşırken, varsayılan
yapılandırıcıyı tanımlamadığım aşağıdaki örneği yazdım.
public class OverloadDeneme
{
private int deger1;
private int deger2;
public OverloadDeneme(int d1,int d2)
{
deger1=d1;
deger2=d2;
}
public OverloadDeneme(int d1)
{
deger1=d1;
}
public void Yaz()
{
System.out.println("Deger1:"+deger1+"
Deger2:"+deger2);
}
}
public class Prog
{
public static void main(String[] args)
{
OverloadDeneme Nesne=new
OverloadDeneme();
Nesne.Yaz();
}
} |
Prog isimli sınıfımı derlemeye çalıştığımda
aşağıdaki hata mesajı ile karşılaştım.

Bir anda ne olmuştuda, new yapılandırıcısı ile
basit bir nesne yaratma işlemi hata ile sonuçlanmıştı. Heyecanla ve birazda
tedirgin bir havayla, kaynaklarımı hızlı hızlı karıştırmaya başladım. Sonrada
Java'nın çok güzel inceliklerinden birini farkettim. Normalde Java, varsayılan
yapıcı metodları bir sınıf için yazmassak bizim için bir tane hazırlıyordu. Ancak
özelleştirilmiş (parametreler alan) yapıcı metodlar tanımladığımızda,
bizim tam anlamıyla konunun hakimi olduğumuzu düşünerek bu varsayılan
yapılandırıcıyı otomatik olarak tanımlama desteğini bir anda çekiveriyordu. Tabir
yerinde ise bizimle bu konuda muhatap bile olmuyordu. Dolayısıyla varsayılan
yapıcı metoduda bizim tanımlamamız gerekiyordu. Bu güzel incelikten yola çıkarak
uygulamayı düzelltim ve hata mesajını ortadan kaldırdım.
C# dilini öğrenmeye ilk başladığım zamanlar
üniversite yıllarında öğrettikleri C++ dilindeki büyük küçük harf ayrımında her
zamanki gibi ilk başlarda çok unutkanlıklar yaşamış ve hep hatalar yapmıştım.
Ama şimdi Java'da gördümkü, unutkanlığa asla yer yok hatta tam anlamıyla dile
hakim olmak esas.
Neyse yapılandırıcıların bu özellikleri ve
işlevlerinden sonra, acaba kendi sınıfımız için özel bir yapılandırıcıya gerek
var mı diye düşünmeye başladım. Bu sınıfa ait nesneler, tablo satırlarını
gösterecek olduğundan, yapılandırıclara parametre atayıp, alan değerleri ile
oynamak son derece anlamsız geldi. Bu nedenle bir yapılandırıcı yazmaktan
vazgeçtim. Ha bu durumda, hiç bir yapılandırıcı yazmadığım için, bu işin
kontrolünü Java'ya bırakmış oldum. O benim için varsayılan bir yapılandırıcı
oluşturacak ve böylece ben uygulamamda new anahtar kelimesi ile rahatça nesneler
yaratabileceğim. Diğer yandan, sınıfımız içine bazı metodlarda eklenebilir.
Örneğin, tüm alan değerlerini düzenlediğimizi düşünelim. Bunun için bir metod
yazabiliriz. Hatta aynı isimli metodu her bir alan için ayrı ayrı uygulayarak,
alanların bireysel olarak düzenlenmesinede imkan sağlayabiliriz diye düşünürken
bu işler için metodlar(set ile başlatan metodlar) yazdığımı farkettim. Ancak toplu bir düzenleme için güzel
bir metod yazılabilirdi. Böylece sınıfa aşağıdaki metodu eklemeye karar verdim.
Bu metod sınıf içindeki alanların değerlerini değiştirecek.
public void Degistir(String ad,String soyad,String
telefon)
{
fAd=ad;
fSoyad=soyad;
fTelefon=telefon;
} |
Bu metodun tek yaptığı, parametre olarak aldığı
String veri türündeki değerleri alarak, sınıf içindeki alan değerlerine atamak.
Sanıyorumki sınıfımın yapısı temel olarak bu şekilde olucak. Artık bu sınıfı ve
bu sınıfa ait nesneleri kullanacağım bir örnek uygulamaya ihtiyacım var. Bu
uygulamada elbette bir sınıf şeklinde tasarlanacak ve mutlaka main metodu
olucak. Main metodu, bir sınıf için başlangıç noktası niteliğindedir. Ama tabiki
tahmin edeceğiniz gibi uygulama içerisinde sadece bir sınıfın main metodu
olmalıdır. Bu bilgiler ışığında, aşağıdaki örnek sınıfı hazırladım.
public class Uygulama
{
public static void main(String[] args)
{
SinifKisi k1=new SinifKisi();
k1.setAd("Burak Selim");
k1.setSoyad("SENYURT");
k1.setTelefon("0000000");
System.out.println(k1.getAd()+"
"+k1.getSoyad()+" "+k1.getTelefon());
k1.Degistir("Burak S.","SENYURT","444
44 44");
System.out.println(k1.getAd()+"
"+k1.getSoyad()+" "+k1.getTelefon());
}
} |
Bu küçük uygulamada, SinifKisi sınıfından k1
isimli bir nesne tanımlıyor ve alanlarının değerlerini değiştirebiliyoruz.
Uygulamayı çalıştırdığımızda aşağıdaki sonucu elde ederiz.

Bu noktada merak ettiğim, sınıf içindeki özel
alanlara erişmek istediğimde nasıl bir sonuç alacağımdı. O nedenle kodlara
aşağıdaki satırları ekledim. Burada açık bir şekilde özel alanlara, tanımlamış
olduğum nesne vasıtasıyla erişmeye çalışıyordum. Bakalım derleyici ne yapacak.
| System.out.println(k1.fAd+" "+k1.fSoyad+" "+k1.fTelefon); |
Sonuçta uygulamayı derlediğimde aşağıdaki hata
mesajları ile karşılaştım. Kapsülleme gerçekleşmişti. Alanları dışarıdaki
sınıflardan soyutlamıştım. Onlara sadece benim tanımladığım metodlar vasıtasıyla
erişilebilecekti.

Aslında sınıflar ile ilgili daha pek çok kavram
vardı kaynaklarımda. Örneğin, static metodlar. Bu metodlar her nesne yönelimli
programlama dilinin önemli bir parçası bence. Bir static metoda ne zaman ihtiyaç
duyabilirdik?
Static metodlar, tanımlandıkları sınıfın
örneklendirilmiş nesnesine ihtiyaç duymadan çalışabilen metodlardır. Dolayısıyla
böyle bir metodu kullanabilmek için, bu metodun tanımlandığı sınıfa ait bir
nesne yaratmak zorunda değiliz. Doğrudan bu metodun tanımlandığı sınıfa ve
pakete nokta notasyonlarını uygulayarak, bu static metodu çalıştırabiliriz.
Böylece sistem kaynaklarını özellikle gereksiz nesnelerle doldurmamış oluruz.
Örneğin matematiksel işlemlerin yapıldığı metodları göz önüne alalım. Bir sayı
dizisindeki elemanları sıralayan bir metod varsayalım. Bu metod mutlaka ve
illaki bir paket içindeki sınıf içinde yer alacaktır. Çünkü nesneye dayalı
programlama dillerinde herşey nesne modeli üzerine kuruludur ve tüm üyeler
sınıflar içerisinde, sınıflarda belli paketler içerisinde yer alır. Paketler ile
ilgilide pek çok kaynak buldum. Açıkçası bir kahve molasındada onlar ile
ilgileneceğim. Java'daki paketlerin yerleşimi aslında kitaplardaki anlatımlar
tarzıyla biraz gözümü korkuttu diyebilirim. Ne demiştik bir sayı disizini
sıralayan metodumuz olsun. Bu metodun tek yapacağı iş, parametre olarak aldığı
dizinin elemanlarına bir sırlama algoritması uygulamak ve sonucu bir dizi olarak
döndürmektir. Bu işi yapması için bir nesneyi görevlendirmek sistem
kaynaklarında sadece but sıralama metodu için yer açmak anlamına gelir. Oysaki
metodumuzu static olarak tanımlarsak, nesne yaratmaya gerek kalmayız. Metodumuzu
ise sınıf.metod notasyonu ile rahatlıkla kullanabiliriz.
Bu düşünceler ışığında acaba küçük uygulamama bu
tip bir static metodu nasıl uygulayabilirim diye düşünmeye başladım. Aklıma bir
metod geldi. Örneğin SinifKisi isimli sınıfa ait nesneleri ekrana düzgün bir
şekilde yazdıracak bir metodum olsaydı. Aslında bu metodu SinifKisi içine
yerleştiripte çağırabilirim. Ama amaç static metodları anlamak olduğu için başka
bir sınıf içine almaya karar verdim. İşte o sınıfın kodları.
public class Yazmaca
{
static void KisiYaz(SinifKisi k)
{
System.out.println("Kişi adı
"+k.getAd());
System.out.println("Kişi soyadı
"+k.getSoyad());
System.out.println("Kişi telefonu
"+k.getTelefon());
}
} |
Bir static metod tanımlama için yapılacak tek iş
metodun tanımlanmasına static anahtar kelimesini eklemek. Buradaki metod
parametre olarak SinifKisi sınıfı tipinden bir nesne örneği alıyor. Şimdi
Uygulama.java dosyamın kodlarını aşağıdaki şekilde yeniledim.
public class Uygulama
{
public static void main(String[] args)
{
SinifKisi k1=new SinifKisi();
k1.setAd("Burak Selim");
k1.setSoyad("SENYURT");
k1.setTelefon("444 44 44");
SinifKisi k2=new SinifKisi();
k2.setAd("Sefer");
k2.setSoyad("ALGAN");
k2.setTelefon("555 55 55");
SinifKisi k3=new SinifKisi();
k3.setAd("Ahmet Faruk");
k3.setSoyad("NACAROGLU");
k3.setTelefon("666 66 66");
SinifKisi[] kisiler=new SinifKisi[3];
kisiler[0]=k1;
kisiler[1]=k2;
kisiler[2]=k3;
foreach(SinifKisi kisi in kisiler)
{
Yazmaca.KisiYaz(kisi);
}
}
} |
Uygulamadaki kodlar bir anda gözüme çok güzel
göründü. Üç tane SinifKisi nesnesi yaratıp alanların değerlerini değiştirmiş ve
bölyece, üç farklı SinifKisi nesnesine sahip olmuştum. Diğer yandan bu nesneleri
SinifKisi tipinden bir diziye aktarmış ve bu dizi içindeki her bir elemanı bir
foreach döngüsünde ele alarak, static KisiYaz metodunu çağırmıştım. Herşey çok
güzel olacak gibi görünüyordu. Ama öyle olmadı. Bam diye bir hata aldım.

Uzunca bir süre düşündüm. Acaba yanlış bir yazımmı
uyguladım diye. Ama sonra dökümanlarımda bu işi araştırmaya başladım. Kimse c#
taki gibi bir foreach döngüsünden bahsetmiyordu. Acaba böyle bir döngü ifadesi
yokmuydu? Ta taaaa.. Hakkatten aradım taradım dökümanlarda bunu bulamadım. Belki
başka bir şekli vardı. Bu amaçla elimdeki e-book lardan O'Reilly basımı 6000
sayfalık java dökümanına baktım. Buradada foreach gibi bir döngüden
bahsedilmiyordu. Sadece For döngülerini bulabildim. Arayışım bittikten sonra,
madem öyle olmuyor bende normal bir for döngüsü kullanırım dedim ve kodları
aşağıdaki gibi değiştirdim.
public class Uygulama
{
public static void main(String[] args)
{
SinifKisi k1=new SinifKisi();
k1.setAd("Burak Selim");
k1.setSoyad("SENYURT");
k1.setTelefon("444 44 44");
SinifKisi k2=new SinifKisi();
k2.setAd("Sefer");
k2.setSoyad("ALGAN");
k2.setTelefon("555 55 55");
SinifKisi k3=new SinifKisi();
k3.setAd("Ahmet Faruk");
k3.setSoyad("NACAROGLU");
k3.setTelefon("666 66 66");
SinifKisi[] kisiler=new SinifKisi[3];
kisiler[0]=k1;
kisiler[1]=k2;
kisiler[2]=k3;
for(int i=0;i<=2;++i)
{
Yazmaca.KisiYaz(kisiler[i]);
}
}
} |
Şimdi oldu işte. Uygulamayı çalıştırdığımda
aşağıdaki sonucu elde ettim. Static metodum olan KisiYaz'a doğrudan sınıf ismi
üzerinden erişmeyi başarabilmiştim.

Sınıflar ile ilgili işlenecek daha pek çok kavram
vardı aslında. Sınıflar arası kalıtım, çok biçimlilik gibi. Ama kahvemde
tükenmişti. Bir süre dinlenmeye ve kaynaklarımı okuyarak yeni bilgiler edinmeye
karar verdim. Kim bilir bir sonraki kahve molamda, hangi rüzgarlara kapılacak,
hangi memleketlere liman açıcaktım. En azından artık sınıfların Java'da nasıl
yazıldıklarını biliyordum. Metodların, özel alanların, static metodların,
yapılandırıcıların...Ama katedilecek daha çok yol vardı. Aslında gönlümden
geçen, bu uygulamda gerçekten veritabanına bağlanıp bir tablodan alanları
alabilmekti. Fakat yolum çok uzun ve sabretmek lazım. Java'da veritabanlarının
işlenmesini çok ama çok merak etmekle birlikte önümde bilmem gereken, Paket
kavramı, applet'ler, gui'ler gibi pek çok konu var. Hadi rast gele diyelim.
Burak Selim ŞENYURT
selim@bsenyurt.com