NESNEYE DAYALI PROGRAMLAMA (NDP)
Nesneye dayalı programlama, (Object Oriented Programming - OOP)- 1970'lerde gelistirilen yordamsal (procedure based) programlama tekniklerinin yerini alan bir programlama yöntemidir. NDP yordamsal programlamadan çok farklı bir düsünme tarzı gerektirir.
Geleneksel yapısal programlamada veri yapıları tasarlanır ve daha sonra veriler teorik olarak kesinlikle sonlanacak sekilde fonksiyonlar ile islenir. Bu fonksiyonlara algoritma denir. Bu nedenle orijinal Pascal'ı tasarlayan Niklaus Wirth ünlü kitabına "Algorithms + Data Structures = Programs" adını vermistir. Algoritmanın önce geldiğine dikkat ediniz, bu o zamanlar programcıların nasıl çalıstığını göstermektedir. Önce verinin nasıl isleneceğine karar verilir; daha sonra islemleri kolaylastırmak için nasıl bir yapı kullanılacağına karar verilir. NDP'da ise bu sıra değisir: veri yapıl 232e41c arı önce yerlestirilir sonra veri üzerinde islem yapan algoritmalara bakılır.
NDP ile gerçeklestirilen yazılımların denetimi, düzeltilmesi ve incelenmesi yapısal programlamaya göre çok daha kolaydır. Çünkü her nesne kendi içinde bağımsız bir bütündür. Diğer nesneler ile iliskileri mesaj göndermekten ibarettir. Her nesne kendi ile ilgili verileri kendi içinde saklar, bazı verilere dısarıdan erisime izin vermeyebilir. Ayrıca programda bir nesnenin güncellenmesi programın bütününde büyük problemlere yol açmaz.
NDP'nin bir diğer avantajı da tekrar
kullanılabilirliğidir. Nesneler neredeyse kendi kendine yeten bir
bütün gibidirler. Programın bir yerinde canlandırıldıktan
sonra yasam sürelerince bellekte kalır ve kendilerine gelen
mesajları değerlendirirler. Nesnelerin bu kadar ayrık birimler
olmaları yeni bir problem çözümü için tekrar kullanılabilmelerine
imkan verir. Yeni problemin nesneleri benzer eski nesnelerden miras
NDP'da en yüksek verimi elde etmek için her nesne birbirleriyle iliskili bir is kümesinden sorumlu tutulmalı. Bir nesne kendi sorumluluğunda olmayan bir isi yapmak istediğinde bu isin sorumluluğunu içeren baska bir nesneye erisebilmelidir. Bunu yapısal programlamadaki fonksiyon çağrılarının bir genellestirilmesi olarak da düsünebiliriz. Java'da bu fonksiyon çağrılarına metod çağrıları (method call) denir. NDP'de ise bu istemcilerin sunucu nesnelere mesaj göndermesi olarak adlandırılır.
Yapısal programlamadaki modüllerde olduğu gibi NDP'de de bağımsız bir nesnenin gereğinden fazla is yapması istenmez. Karmasık verileri içieren ve verileri islemek için yüzlerce fonksiyon içeren büyük nesneler yerine birkaç isi gerçeklestiren küçük nesneler yaratıldığında tasarım ve hata düzeltme safhaları basitlesecektir.
NDP'de programınız belirli özellikleri ve islemleri gerçeklestirebilen nesnelerden olusmaktadır. Nesne birbiriyle iliskili durumlar ve islemler kümesidir. Genellikle bir nesneye ait bir islem gerçeklestiğinde nesneye ait durumlardan bazıları değisir. Aynı sekilde islemler de bazı durumların değerine göre davranır.
Sınıf nesnenin yapıldığı kalıp veya sablon olarak tanımlanabilir. Bir sınıfa ait bir nesne yarattığınızda o sınıfın bir örneğini yaratmıs olursunuz.
Örneğin, birbirinden çok farklı bir yığın kediyi "kedi" adı verilen soyut bir sınıfın üyelerine indirgeyerek algılarız. Kedilerin en genel özelliklerini ve davranıslarını içinde barındıran "kedi" kavramı (sınıfı) düsünüldüğünde, akla kedilerin sadece fiziksel özellikleri yada sadece davranısları gelmez, aksine bir bütün olarak hem davranıs hem de fiziksel özellikleri algılanır. Kedi denildiğinde akla hem kedilerin tüylü, kuyruklu olması gibi özellikler hem de miyavlama, tırmalama gibi özellikler gelir.
Karsımıza yeni bir kedi geldiğinde bu yeni kediyi kedi sınıfının bir örneği olarak algılarız. Kedilere ait bütün ortak özellikleri bu kediye atarız. Ancak kediyi biraz dikkatle incelersek onda her kedide olmayan farklılıklar buluruz. Artık bu kedi hakkında aklımızda sadece kedi sınıfının bir örneği olmasıne ek olarak bu farklı özellikleri de saklarız. Böylece özel bir kediyi kedi sınıfına dahil olması ve farklılıkları olarak çok az veriyle tanımlamıs oluruz.
Sınıf ile nesne arasındaki iliskiyi pasta kalıbı ile pastanın kendisi arasındaki iliskiye benzetebiliriz. Sınıf pastanın kalıbına, nesne ise pastaya karsı düser. Pastanın hamuru ise burada belleğe karsı düser. Java bu hamur hazırlama yani bellek ayrıma islemini kullanıcıdan saklama konusunda oldukça basarılıdır. Java'da bellek ayırmak için new anahtar kelimesi kullanılmaktadır.
Pasta pastam = new Pasta();
NDP'nin temel özellikleri:
Miras alma (Inheritance)
Kümeleme (Encapsulation)
NDP'nin en temel özelliği olan kümeleme bir nesneye ait özelliklerin ve davranısların nesne için bir bütün olarak saklanması anlamına gelir.
Java'da yazılan hersey bir sınıfın içindedir. Java birçok sınıftan olusmustur. NDP mantığının getirdiği bir bir kolaylık vardır: sınıflar genellikle (Java 'da her zaman) diğer sınıflar üzerine bina edilir. Java, gerçekte, bütün diğer sınıfların türetildiği bir kozmik taban sınıfı ile gelmektedir. Bu sınıf Object olarak adlandırılmıstır. Java'da bütün sınıflar bu Object adlı sınıftan türetilmistir. Java'da bir sınıfın diğer bir sınıftan miras aldığını belirtmek için extends kelimesi kullanılır.
Geleneksel yordamsal programlamada main fonksiyonu ile en yukardaki süreçten baslarsınız. Nesneye dayalı bir sistem tasarlarken en yukarıdaki diye bir kavram yoktur, bu nedenle NDP ile yeni tanısanlar için nereden baslayacakları önemli bir sorundur. Önce sınıflar bulunur sonra her sınıfa metod eklenir.
Sınıfları tanımlarken takip edilebilecek bir yol problem analizinde isimlere bakmak, aynı sekilde metodlar da fiillere karsı düser.
Sınıflar arasındaki en yaygın iliskiler:
Kullanmak (use)
Kapsamak (containment)
miras almak (inheritance)
A sınıfı B
sınıfını kullanır
A'nın bir metodu B sınıfından bir nesne yaratır, alır veya döndürürse
Birbirini kullanan sınıf sayısını minimize ederek bir sınıftaki bir hatanın veya değisikliğin diğer bir sınıfı etkilememesi sağlanabilir.
Kapsama iliskisi ise kullanma iliskisinin
özel bir halidir.
Miras alma iliskisi özellesmeyi ifade
eder. Genel olarak,
Nesne Değiskenleri
Java'daki çoğu sınıflar için önce nesneler yaratılır, baslangıç durumlarıı belirlenir, sonra nesnelerle çalısılır.
Nesnelere erismek için nesne değiskenleri tanımlanır. Örneğin
Kedi kedim ;
Ancak bu satır ile kedim bir nesneye isaret etmemektedir. Bir nesne yatamak için new kelimesi kullanılmalıdır.
Kedi kedim = new Kedi();
Böylece Kedi nesnesinden bir örnek yaratılır. Artık Kedi sınıfının metodlarını kedim nesnesine uygulayabilirsiniz.
Kedi boncuk = kedim;
Satırı yazıldığında yeni bir nesne yaratılmamıs olup, boncuk kedim ile aynı nesneyi isaret etmektedir.
kedim.miyavla();
boncuk.sus();
seklinde iki satır yazıldığında kedim nesnesi önce miyavlayacak sonra da susacaktır.
Çoğu sınıfın clone adında bir metodu vardır. Bu metod bir nesenin gerçek kopyasını çıkartır. "=" isleminden farklı olarak burada nesneler birbirinden bağımsızdır, yani zamanla birbirinden ayrılırlar.
Bir nesne değiskeninin o an için hiç bir nesneyi isaret etmediğini belirtmek için null değerini kullanabilirsiniz.
kedim = null;
....
if (kedim != null) kedim.miyavla();
Java'daki nesne değiskenleri C++'daki nesne isaretçilerine benzemektedir.
Kedi kedim; // Java
Kedi* kedim;// C++
Kedi* kedim = new Kedi(); // C++
Java'da bütün nesneler
yığında yasar.
Java ile birlikte gelen bir Date sınıfı vardır. Date sınıfının bir örneği epoch olarak adlandırılan sabit bir noktadan milisaniyelerin sayıldığı bir duruma sahiptir. Bu sınıf tarihi "December 31, 1999" seklinde ifade etmektedir. Ancak bu verilerin yeterli olmadığı "December 31, 1999 ,23:59:59" ifadesinin daha uygun olduğuna karar verilerek Java1.1'de GregorianCalendae isimli bir sınıf eklenmistir. Gregorian takvimi dünyanın çoğu yerinde kullanılan bir takvimdir.
GregorianCalender bugun = new GregorianCalender();
satırı sunları yapar:
bugun olarak adlandırılan yeni bir GregorianCalender sınıfının örneğini yaratır.
Aynı zamanda bugun nesnesinin durumunu o anki tarih olarak atar.
Ayrıca özel bir tarih için de bu sınıftan bir nesne yaratabilirsiniz.
GregorianCalender birgun = new GregorianCalender(1999,11,31);
Bu tarih Aralık 31, 1999 'i ifade eder. Bu metod için aylar 0'dan baslamaktadır, bu nedenle 11 Aralık ayını ifade etmektedir. Ayrıca bu sınıf ile saati de verebilirsiniz.
GregorianCalender bugun = new GregorianCalender(1999,11,31,23,59,59);
Asağıda GregorianCalender sınıfının kullanıslı birkaç metodu verilmistir:
GregorianCalender()
Default olarak tanımlanmıs zaman kusağında ve yerel takvim nesnesi yaratır.
GregorianCalender(int year, int month, int date)
Verilen tarihte bir nesne yaratır.
GregorianCalender(int year, int month, int date, int hour, int minutes, int seconds)
Verilen tarih ve saatte bir Gregorian takvimi yaratır.
boolean equals(Object when)
Bu takvim nesnesi ile when nesnesini
karsılastırır ve
boolean before(Object when)
Bu takvim nesnesi ile when nesnesini
karsılastırır ve
boolean after(Object when)
Bu takvim nesnesi ile when nesnesini
karsılastırır ve
int get(int field)
Belirli bir değiskenin değerini geri döndürür. Bu değiskenler asağıdakilerden biri olabilir:
Calender.ERA
Calender.YEAR
Calender.MONTH
Calender.WEEK_OF_YEAR
Calender.WEEK_OF_MONTH
Calender.DATE
Calender.DAY_OF_MONTH
Calender.DAY_OF_YEAR
Calender.DAY_OF_WEEK
Calender.DAY_OF_WEEK_IN_MONTH
Calender.AM_PM
Calender.HOUR
Calender.HOUR_OF_DAY
Calender.MINUTE
Calender.SECOND
Calender.MILLISECOND
Calender.ZONE_OFFSET
Calender.DST_OFFSET
void set(int field, int value)
Belirli bir değiskenin değerini atar. Bu değiskenler get metodundakiler ile aynıdır.
void set(int year, int month, int date)
Tarih değiskenlerine yeni değer atar.
void set(int year, int month, int date, int hour, int minutes, int seconds)
Tarih ve saat değiskenlerine yeni değer atar.
void add(int field, int amount)
Veri üzerinde aritmetik islem yapar. Belirli bir değiskene amount ile belirtilen miktarı ekler. Örneğin 7 gün eklenecekse asağıdaki yazılır:
add(Calender.DATE, 7)
Değistiren ve Erisen Metodlar
GregorianCalender'ın metodlarının adlandırması çoğu nesneninkinden farklıdır. Genelde setYear, getYear gibi metod adları verilirken bu sınıf için sadece get veya set metodu ile istenilen değer parametre olarak aktarılır. Yani yıl değerini döndürmek için getYear yerine get(Calender.YEAR) gibi bir metod kullanılmaktadır. Ancak çoğu sınıfta metodlar set veya get kelimelerinden sonra büyük harfle baslayan kelimeler seklinde adlandırılır.
Bu sınıfta set ve add metodları veri üzerinde değisiklik yaptığından değistiren metod (mutator method) olarak adlandırılırken get metodu sadece veriye erisim sağladığı için erisen metod (accessor method) olarak adlandırılır.
Corejava kitabında kullanıcı için daha uygun bir sınıf olan Day sınıfı gelistirilmistir. Bu sınıfta bir nesne su sekilde yaratılabilir:
Day bugun = new Day(); // veya
Day birgun = new Day(1999, 12, 31);
Burada aylar 1'den baslamakta, aralık ayı da 12 olmaktadır. Bu sınıfı kullanmak için Java'nın bu sınıfın nerde olduğunu bilmesi gerekir. Bunun için CLASSPATH değiskeni gerektiği gibi ayarlanmalıdır.
Asağıda Day sınıfının durumunu etkileyen metodlar verilmistir:
void advance(int n)
O anki tarihe n gün ekler. Örneğin d.advance(100) d tarihini 100 gün sonrası olarak değistirir.
int getDay(), int getMonth(), int getYear()
Day nesnesinin gün, ay ve yıl değerini döndürür. Günler 1 ile 31, aylar 1 ile 12 arasında değer alabilir, yıl ise her yıl olabilir.
int weekday()
Haftanın kaçıncı günü olduğunu döndürür. 0-6 arasında değer alır ve 0 pazar gününe karsı düser.
int daysBetween(Day b)
Day sınıfının yaratılmasının en önemli sebebi bu metod. O anki Day sınıfının örneğinin tarihi ile b nesnesinin tarihi arasındaki gün sayısını hesaplar.
Asağıda doğumgününden itibaren bugune kadar kaç gün geçtiğini hesaplayan basit bir program kodu verilmistir:
import corejava.*;
public class YasananGun
}
import corejava.*;
public class Calendar
else
Day d = new Day(y, m, 1); // start date of the month
System.out.println(m + " " + y);
System.out.println("Sun Mon Tue Wed Thu Fri Sat");
for( int i = 0; i < d.weekday(); i++ )
System.out.print(" ");
while (d.getMonth() == m)
if (d.weekday() != 0) System.out.println("");
}
}
Java sınıfının en basit ifadesi asağıda verilmistir.
Class SınıfınAdı
Çoğu Java programında birden fazla sınıf tanımlanır bir sınıf dğier sınıfların nesnelerini kullanır. Asağıda Employee sınıfını içeren EmployeeTest sınfı örneği verilmistir.
Örnek: EmployeeTest sınıfı
import java.util.*;
import corejava.*;
public class EmployeeTest
}
class Employee
public void print()
public void raiseSalary(double byPercent)
public int hireYear()
private String name;
private double salary;
private Day hireDay;
}
Employee sınıfındaki metodları incelersek:
public Employee(String n, double s, Day d)
public void print()
public void raiseSalary(double byPercent)
public int hireYear()
Buradaki public kelimesi erisim tanımlayıcısıdır. Java'da bu çerisim tanımlayıcıları bu metodu kimlerin kullanabileceğini belirler. public kelimesi, Employee sınıfının bir örneğine erisebilen herhangi bir sınıfın herhangi bir metodu bu metodu çağırabilir anlamına gelir.
Employee sınıfındaki değiskenleri incelersek:
private String name;
private double salary;
private Day hireDay;
Buradaki private kelimesi Employee sınıfının metodları haricinde dısarıdan hiçbir programın bu değiskene erisemeyeceğini ifade eder. Genellikle sınıf içindeki değiskenler private olarak tanımlanır; sadece birbiriyle sıkı iliskide bulunan sınıflar sözkonusu olduğunda farklı bir durum olabilir.
Burada hireDay değiskeninin baska bir nesnenin örneği olduğuna dikkat ediniz. Sınıflar çoğunlukla baska sınıfların örneklerini değisken olarak içerirler.
Employee sınıfındaki ilk metoda bakarsak:
public Employee(String n, double s, Day d)
Bu constructor metodu örneğidir. Constructor metodları sınıfın içindeki değiskenlere baslangıç durumlarını vermek o sınıftan örnek nesne yaratmak için kullanılır.
Bir sınıfı yaratmak için new kelimesi constructor ile birlikte kullanılır. Bu da nesnelerin baslangıç durumlarını mutlaka belirtmenizi gerektirir. Java'da bir sınıfın örneğini yani bir nesneyi o sınıfın değiskenlerine baslangıç değeri vermeden yaratamazsınız. Bunun sebebi baslangıç durumu yaratılmayan bir nesnenin gereksiz ve anlamsız olmasıdır.
Constructor'ların özellikleri:
Constructor ile sınıfın adı aynıdır.
Bir constructor bir veya daha fazla (hatta hiç) parametreye sahip olabilir.
Bir constructor her zaman new kelimesi ile çağrılır.
Bir constructor'un hiç bir zaman döndürdüğü değer yoktur.
Bir constructor sadece kelimesi ile çağrılabilir, değiskenlerin değerini reset etmek için var olan bir nesnenin constructor'unu çağıramazsiniz. Örneğin d.Day(1950, 1, 1) diyemezsiniz. Böyle bir durumda bu isi yapacak değistiren metodlar (örneğin reset gibi) tanımlanabilir.
Bir sınıfın birden fazla construtor'u olabilir. Bunun örneğini GregorianCalendar sınıfında ve Day sınıfında zaten görmüstünüz.
Burda dikkat edilmesi gereken diğer bir husus metodların içinde kullanılan yerel değiskenlerin sınıfın değiskenleri ile aynı adı tasımamasıdır; aksi halde yerel değisken sınıfın değiskeninin önüne geçer.
Employee sınıfının metodları incelendiğinde sınıfın değiskenlerine doğrudan erisim olduğu görülür. Örneğin,
public void raiseSalary(double byPercent)
metodunda salary, Employee sınıfının bir değiskenidir. Bu metod salary değiskeninin değerini değistirmektedir, geriye bir değer döndürmemektedir.
ahmet.raiseSalary(5);
Çağrısı ahmet'in maasını %5 arttırır.
public int hireYear()
Metodu ise geriye bir değer döndürmektedir.
Çoğu sınıfta private veri değiskenleri sadece islemleri gerçeklestirenleri ilgilendirir. Eğer bir sınıfın kullanıcısı bir değiskene değer atamak ve değiskenin değerini okumak istiyorsa sınıfı gerçeklestirenlerin tanımlaması gerekenler:
Bir private veri değiskeni
Bir public değiskene erisim metodu
Bir public değiskeni değistiren metod
Bu, sadece bir tane public veri değiskeni tanımlamaktan daha yorucu bir islem olmasına rağmen bir çok avantajı vardır:
Sınıfın içindeki yapı değistirilirken bu sınıfın islemleri dısında hiç bir propgram kodu etkilenmez.
Basitçe bir değiskeni değistiren bir kod hata kontrolü yapamazken, değistiren metodlar hata kontrolü yapabilir
Dikkat edilmesi gereken diğer bir konu da değistirilebilen nesnelere referansları geri döndüren erisen metodların yazılmaması. Örneğin:
class Employee
public Day getHireDay()
private String name;
private double salary;
private Day hireDay;
Bu encapsulation özelliğini bozar. Asağıdaki kodun yazıldığını düsünün:
Employee ahmet= . . . ;
Day d = ahmet.getHireDay();
d.advance(10);
Hem d hem de ahmet.hireDay aynı nesneye isaret eder. d 'yi değisince otomatikman employee nesnesinin durumu da değisir. Day nesnesi değisebilir olduğundan ve advance değitiren metod olduğundan d'nin değismesi ile birlikte ahmet.hireDay nesnesi de değisir. Bu ise dısarıdan bir nesnenin durumunun değistirilmesi demek bu encapsulation'a aykırıdır.
Çözüm ise erisen metoda hireDay değiskenini geri dödürmeden önce bir kopyasının clone metodu ile alınmasıdır.
class Employee
Private verilere metod ile erisim
İki tarihi karsılastıran asağıdaki compare metodunu inceleyelim.
class Day
}
Bir çağrıya örnek:
if ( hireday.equals(d)) . . .
Private metodlar
Public veriler tehlikeli olduğu için metodlar da değiskenler gibi private olabilir. Bu metodlar sadece o sınıftaki diğer metodlar tarafından çağrılabilir. Böyle metodların kullanımı özellikle programcının islemleri parçalaması ve bu parçaların bir kısmının genel kullanım için uygun olmaması sonucu olusur. Bu metodlar sınıf dısında kullanılmazlar.
Java'da bir metodu private yapmak için public kelimesi yerine private kelimesinin yazılması yeterlidir.
Sınıf kullanıcısı ile ilgisi olmayan ve sınıfın uygulaması değistirilince desteklenmeyecek metodları private tanımlayın.
Static metodlar
Değiskenleri ve netodları static tanımlayabilirsiniz. Static değiskenler sınıfın durumu değisse bile değismeyen özelliklerdir. Benzer sekilde static metodlar sınıfın hiç bir değiskeni (davranısı) üzerinde islem yapmaz. Bu demektir ki, static metodları sınıfını bir örneğini yaratmadan kullanabilirsiniz.
Örneğin Java'nın Math sınıfının bütün metodları static olarak tanımlanmıstır.
Double x = Math.pow(3,0.1);
Bir sınıfın sırasıyla bir static metodu ve bir static değiskeni su formda çağrılır
SınıfAdı.StatikMetod(parametreler);
SınıfAdı.StatikDeğiskenAdı;
Bir diğer örnek olarak
Public static void main(String[] args)
verilebilir. main static olarak tanımlandığından onu çağırmak için o sınıftan bir örneği yaratmanız gerekmemektedir. Java yorumlayıcısı main metodunu o sınıfın bir örneği yaratılmadan otomatikman çalıstırmaktadır. Birçok main metodunun kendi sınıfının bir örneğini yarattığına dikkat ediniz.
Örnek: RandomIntGenerator
Bu sınıf Corejava'da bulunmakta ve Java'nın rastgele sayı üreten java.lang.Math.random() metodu yerine gelistirilmistir.
RandomIntGenerator k = new Ran.(10,20,30);
package corejava;
public class RandomIntGenerator
/**
* Used to return a random integer in the range constructed
*/
public int draw()
/**
* test stub for the class
*/
public static void main(String[] args)
private static double nextRandom()
private static final int BUFFER_SIZE = 101;
private static double[] buffer
= new double[BUFFER_SIZE];
static
private int low;
private int high;
}
Sınıfın çalısması su sekildedir:
Java'da bulunan rastgele tamsayı üretecini kullanarak küçük bir dizi olusturur. Dizinin kendisi ve boyu private static final kelimeleri ile sabit olarak tanımlanmıstır. Böylece bu sınıfın her örneği bu bilgiyi paylasabilir.
Belirlenen aralıkta rastgele sayıyı çizmek için draw adında bir public metodu var. Bu metodu kullanmak için RandomIntGenerator sınıfının bir örneğini yaratmanız gerekir.
Draw metodu aslında nextRandom olarak adlandırılan bir satic metod kullanmaktadır. Bu metod Donald E. Knuth''un Semi-Numerical Algorithms sf. 32 'deki algoritmasını uygulamaktadır. Bu metod Java'nın standart rastgele sayı üretecini 2 kez kullanmaktadır: birincisinde dizinin kaçıncı elemenı olduğunu belirlemek için, ikincisi ise sayının değerini belirlemek için. Bütün RandomIntGenerator sınıfının örnekleri bu islemleri içereceğinden bu metod static olarak tanımlanmıstır.
Burada static baslangıç atama bloğu yapısı kullanılmıstır. Bu blok yapısı, sınıfın static üyelerinin baslangıç durumu atamalarının yapılamadığı veya zor olacağı zaman kullanılır. Örneğin burada RandomIntGenerator sınıfı nextRandom metodunu ilk kez çağırmadan önce diziye baslangıç değeri atanmalıdır. Bunun için bir döngü olusturulmalı, döngü yapısı da basit olmadığından static baslangıç atama bloğu kullanılmıstır. Bu blok static kelimesi ile baslar arasında yazılır. Java, herhangi bir metodu çağırmadan bir kez bu static bloğu içindekileri gerçeklestirir. Bu bloklarda sadece static olarak tanımlanmıs verilere erisilebilir. Programınızda istediğiniz sayıda static baslangıç atama blokları kullanabilirsiniz, Java yukarıdan asağıya doğru bunları çalıstırır.
Sınıfın constructor 'ı sayıların sınırını belirlemektedir.
Overloading
Aynı isme fakat farklı parametrelere sahip birden fazla metodun olmasına "overloading" denir. Örnek olarak Day sınıfındaki
Day() ve
Day(int year, int month, int day)
Constructor'ları verilebilir. Java derleyicisi, parametrelerin farklı olmasından faydalanarak ilgili parametrelere sahip ilgili metodu bulur ve çağırır.
Sınıf değiskenine baslangıç değerinin atanması
Sınıf değiskenlerine baslangıç değeri atanmadıysa Java kendiliğinden 0, null veya false değeri atar. Ancak bu iyi bir programlama özelliği değildir, durumlara baslangıç değerlerinin atanması her zaman faydalıdır.
Eğer tüm constructor'ların belirli bir sınıf değiskenine aynı değeri atamaları gerekirse sınıf içindeki değiskene değer atamaları yeterlidir. Örneğin:
class Customer
Bu, tüm constructor'lar aynı değiskene aynı değeri atayacaksa çok kullanıslı bir yöntemdir.
Eğer sınıfınızı tanımlarken constructor kullanmazsanız Java default constructor tanımlar ve tüm değiskenleri sıfırlar.
this nesne isaretçisi
Bir metodda this kelimesi o metodun bulunduğu nesneyi ifade eder. Örneğin çoğu Java sınıfının ekrana yazdırmak için toString metodu vardır. Date sınıfını ele alalım. Bir tarih değiskeninde saklı o anki tarih bilgisini yazdırmak için this.toString() yeterlidir. Bu özellikle hata düzeltmede çok kullanılır.
this kelimesini baska bir anlamı daha vardır, o da bir constructor'ın ilk satırında this(.) seklinde bir ifade varsa o constructor aynı sınıfın bir baska constructor'ını çağırır. Örneğin,
class Customer
private Customer ( String n, int a)
}
finalize() metodu
Java kullanılmayan belleği otomatikman silmektedir. Bazı nesneler bellek dısında bazı özkaynaklar üzerinde islem yapabilir, bu durumda Java finalize metodunu kullanmanıza izin verir. Bu metod garbage collector belleği bosaltmadan önce çağrılır.
Örnek: CardDeck sınıfı
Bu program basit bir kart oyunudur. Program biri kendisi için biri sizin için. Olmak üzere iki kart seçer, büyük olan kazanır. CardDeck sınıfı Card sınıfını kullanmaktadır.
Bir kartın 1- 13'e kadar sayısal değeri ve 1-4 arasında türünü ifade etmek için tür değeri vardır. Asağıda Card sınıfı verilmistir.
public final class Card
public int getValue()
public int getSuit()
public int rank()
public String toString()
private int value;
private int suit;
}
Card'ın constructor'ının sayısal değeri ve türü olmak üzere iki tamsayı parametresi vardır. Asağıda CardDeck sınıfı görülmektedir.
import corejava.*;
public class CardDeck
public void fill()
public void shuffle()
}
public final Card draw()
public static void main(String[] args)
else
System.out.println("I win");
}
System.out.println
("Your wins: " + wins + " My wins: " + (rounds - wins));
}
private Card[] deck;
private int cards;
}
CardDeck sınıfının cards değiskeni kart sayısını vermektedir. Baslangıçta 52 kart vardır, kart çektikçe sayı azalacaktır.
CardDeck'in constructor'ı card nesnesinin dizisine baslangıç değeri atamaktadır. Dizi yaratıldıktan sonra fill metodu ile 52 kart olusturulur.
En son gelen kartın rastgele seçimi shuffle metodu ile gerçeklestirilir, sonra da seçilen kart ile bu kart yer değistirir.
Paketler
Java, sınıfları paket olarak adlandırılan gruplara toplamanıza imkan verir. Standart Java kütüphanesi java.lang, java.util, java.net vb. bir çok paketten olusur. Bu paketler hiyerarsik paketlerdir. Bütün Java paketleri java paket hiyerarsisinin içindedir.
Paket yazarken kaynak kodunun en üst kısmına paketin adını yazmalısınız. Örneğin GregorianCalendar sınıfına bakarsanız açıklamalardan sonraki ilk satırda su ifadeyi görürsünüz.
package java.util;
Bu GregorianCalendar.java'ın java.util paketinin bir parçası olduğunu ifade eder. Eğer kaynak dosyanızın paket tanımı yoksa Java onu default paketine ekler.
Paketleri kullanmak
Paketleri Java programlarında iki sekilde kullanabilirsibniz. Birincisi paketin tam adını yazarak, örneğin corejava.Console.readInteger() . Bu çok yorucu ve gereksizdir. İkinci yöntem ise import kelimesinin kullanımıdır. Bu kelime ile belirli bir sınfı veya genel olarak paketi kullanabilirsiniz. import kelimesini kaynak kod o paketi kullanmadan önce yazmalısınız.
import java.util.*; // java.util paketindeki bütün sınıflara erisim sağlar.
* isaretini o bir paket için kullanabilirsiniz, fakat java.* deyip java'nın altındaki bütün paketlere erisemezsiniz.
Derleyicinin paketleri yerlestirmesi
Bütün paket, paket adı ile aynı ada sahip bir dizinin altında olmalıdır. Örneğin java.util paketi java\util dizininin altındadır.
Bu dizinler kökün altında olabileceği gibi CLASSPATH ile tanımlanan dizinin altında da bulunabilirler. Örneğin,
CLASSPATH = c:\jdk\lib; c:\CoreJavaBook;.;
olarak tanımlansın ve programda su satırlar yazsın:
import java.util.*;
import corejava.*;
Java derleyicisi Console sınıfını bulmak için su dizinlere bakar:
C:\jdk\lib\console.class
C:\jdk\lib\corejava\console.class
C:\jdk\lib\java\util\console.class
C:\CoreJavaBook\console.class
C:\CoreJavaBook\java\util\console.class
C:\CoreJavaBook\corejava\console.class
.\console.class
.\corejava\console.class
.\java\util\console.class
Aslında java.util paketine bakarsanız bunun bulunmadığını fakat onun yerine classes.zip seklinde bir dosyada ziplenmis olarak durduğunu görürsünüz. Siz de tanımladığınız paketi zip dosyası olarak koyabilirsiniz.
Java her zaman java.lang paketini çağırdığından bu paketi tanımlamaya veya import kelimesi ile belirtmeye gerek yoktur.
Eğer bir sınıfı, metodu veya değiskeni public veya private olarak tanımlamazsanız aynı paketteki tüm sınıflar tarafından buna erisilebilir. Özellikle metodlar için mutlaka private yada public tanımı yapılmalıdır.
Sınıf tasarlarken dikkat edilecek bazı husular:
Her zaman veriyi private olarak tanımlayın .
Her zaman veriye ilk değeri atayın.
Bir sınıfta çok fazla basit tip kullanmayın. Örneğin
private String street;
private String city;
private String state;
yerine Address adında yeni bir sınıf yaratın.
Bütün değiskenler için erisen veya değistiren metod tanımlamak gerekmez.
Sınıf tanımlamaları için standart bir form kullanın, sınıfların içeriğini belirli bir sırada ve düzende yazın.
Çok fazla is yapan sınıfları bir kaç sınıfa bölün.
Sınıf ve metodları yaptıkları isi belirtecek sekilde adlandırın.
|