Kurucular

(Constructors)

 

 

Kurucunun (kurucu) ne yaptığını anlamak için sınıfın (class) ne olduğunu anımsamak gerekir. Sınıfın yalnızca bir tür-adı (cins-isim) olduğunu söylemiştik. Sınıf tanımı o türün niteliklerini (değişkenler)  ve davranışlarını (metotlar) belirler. Elimizde o türe ait somut bir öğe (türü temsil eden varlık) varsa, o öğe, sözkonusu türün niteliklerine ve davranışlarına işlevlik kazandırır. Dolayısıyla, bir sınıftan, o türe ait öğe(ler) yaratmanın yolları olmalıdır. Genel olarak, bir sınıftan bir nesne yaratmak için new anahtar sözcüğünü kullanmayı öğrendik. Örneğin,

Class Deneme

{

}

sınıfından bir nesne yaratmak istediğimizde

Deneme  dnm = new Deneme();

deyimini kullanıyoruz. Bu deyim ana bellekte dnm işaretçisinin yerini işaret ettiği bir nesne yaratır.

Bir sınıf tanımlandığında, bellekte henüz onu temsil edecek öğeler yoktur (static sınıflar hariç). Her sınıf için bu işi yapan özel bir metot vardır. Bu metoda kurucu (kurucu) diyoruz. Kurucunın görevi tür ait öğe(ler) yaratmaktır. Java dilinde bu öğelere nesne (object, instance of the class) denir. Kurucu (kurucu), yaratılan sınıfın doğal bir parçasıdır ve aksi istenmedikçe öntanımlı (default) olarak derleyici tarafından oluşturulur ve kendi işlevini yapar. Kurucu bir metot gibidir, ama javadaki öteki metotlardan tamamen farklıdır. Bu metodun bir değer-bölgesi yoktur; yani hiçbir değer almaz. Bir tek işlevi vardır: sınıftan nesne(ler) yaratmak.

Bir sınıftan bir nesnenin kurulması (instantiate) demek  onun için ana bellekte bir yer ayrılması, sınıfın değişkenlerine başlangıç değerlerinin verilmesi ve varsa sınıfın fonksiyonlarının etkin duruma sokulması demektir. Bu iş yapılmadan, sınıf hiçbir işleve sahip değildir; sınıfın nitelikleri ve davranışları ancak bu nesnelerde görülebilir. Başka bir deyişle, statik olmayan bir sınıf içinde tanımlanan  değişkenler ve metotlar ancak bir nesne içinde hayat bulurlar.

Bir sınıftan istenildiği kadar nesne yaratılabilir. Yaratılan her nesne için ana bellekte o nesneye özgü ve öteki nesnelerinkinden farklı bir yer ayrılır. 

Bir sınıf içinde static nitelemi olan değişkenlere statik değişkenler (sınıf değişkenleri, class variables) ve static nitelemi olan metotlara statik metotlar (sınıf metotları, class methods) denir.

Bir sınıf içinde static olmayan değişkenlere dinamik değişkenler (anlık değişkenler, instant variables) ve static olmayan metotlara adinamik metotlar (anlık metotlar, instant methods) denir.

Nesne yaratılırken, derleyici tarafından otomatik olarak oluşturulan kurucu’ya öntanımlı kurucu (default kurucu) demiştik. Öntanımlı kurucu hiçbir parametresi olmayan ve sınıf ile aynı adı taşıyan bir metottur. Ancak, kurucu bir metot gibi olduğundan, istenirse aşkın yükleme (overload) yapılabilir, yani farklı parametrelerle farklı işlevlere sahip kılınabilir. Böyle bir kurucu tanımlanınca, öntanımlı olan kurucu kendiliğinden yok olur, onun işlevini tanımlanan kurucu üstlenir. Derleyicinin yaratacağı öntanımlı kurucu yerine, bir çok uygulamada daha işlevsel olması için aşkın kurucu tanımlanır. 

 

 Örnek l:          Aşağıdaki sınıf öntanımlı kurucuyu (default  kurucu) kullanmaktadır. Dinamik nesne (anlık nesne, instance of the class) yaratmaya gerek kalmadan,  öntanımlı kurucu ana bellekte Daire1 için bir yer ayırmaktadır.

class Daire1 {

  public static void main (String args[]) {

            int  yarıçap;

            double çevre;

            double alan;

            final double pi = 3.14;

            yarıçap = 7;

            alan = pi * yarıçap * yarıçap;

            çevre = 2 * pi * yarıçap;

            System.out.println ("Dairenin Alanı : " +alan);

            System.out.println ("Dairenin Çevresi  : " + çevre);

      }

}    

 

Alıştırmalar :

1.  Yukarıdaki programda pi değişkeni final damgasını taşıdığı için sabittir, program koşarken değeri  değiştirilemez. Bu değeri değiştirmeye kalkarsanız, derleme hatası oluşur. Örneğin,  6-ncı satırdan sonraki herhangi bir satıra pi = 3.1416 gibi bir deyim ekleyip, derleyicinin verdiği uyarıyı görünüz.  

2.  Programdaki öteki üç değişken  main() metodunun yerel (local) değişkenleridir. Bunlara, bazen iç-değişkenler  ya da metot değişkenleri  denir. Bir metot kendi iç değişkenlerine her zaman erişebilir, program koşarken değerlerini değiştirebilir.

 

 

Örnek 2:          Aşağıdaki sınıf öntanımlı kurucuyu  kullanmaktadır. Sınıfın dört tane static değişkeni vardır, onlardan birisi final damgasını aldığı için sabittir. Statik değişkenler için ana bellekte yalnızca birer tane yer ayrılır. Bu demektir ki, statik değişkenlerin ana bellekte başka kopyaları olamaz. Program koşarken statik değişkenin değeri değişebilir, ama bir statik değişken programda son girilen değeri saklayabilir, önceki değerler o adresten (dolayısıyla bellekten) ebediyen silinmiş olur.

class Daire2 {

             static int          yarıçap;

             static double       çevre;

             static double       alan;

             final static double pi = 3.14;

 

  public static void main (String args[]) {

             yarıçap = 4;

             alan = pi * yarıçap * yarıçap;

             çevre = 2 * pi * yarıçap;

 

             System.out.println ("Dairenin Alanı   : " + alan);

             System.out.println ("Dairenin Çevresi : " + çevre);

       }     

}

Alıştırmalar :    

3.       Yukarıdaki programda her hangi bir değişkenin önündeki static nitemini kaldırıp programı derlemeyi deneyin. Derleme hatası oluşacaktır. Bunun nedeni şudur:  main() metodu static ‘tir ve statik metotlar ancak statik değişkenlere erişebilirler.

4.       Statik olmayan metotlar (bunlara dinamik , anlık –instance- metot diyoruz) hem statik hem anlık değişkenlere erişebilirler.

 

 

Örnek 3a.         Aşağıdaki sınıf öntanımlı kurucuyu  apaçık kullanarak bir nesne yaratmaktadır. 8-inci satırda nesne yaratılırken o nesneye erişimi sağlayacak referans (pointer) da tanımlanmaktadır. Bu referansın (pointer) adı d  dir.  d  referansı nesnenin kendisini değil, yalnızca nesnenin bellekteki adresini tutar. O adrese bu referansla erişebiliriz. Nesnenin yarıçap adlı değişkenine erişmek için d.yarıçap, yazılır. Bunun anlamı şudur: d  referansının gösterdiği adresteki yarıçap adlı değişken. Öteki değişkenlere erişmek için de d.çevre, d.alan, d.pi yazılır.

class Daire3a {

             static int yarıçap;

             static double çevre;

             static double alan;

             final static double pi = 3.14;

  public static void main (String args[]) {

             // öntanımlı kurucu nesne yaratıyor

       Daire3a d = new Daire3a();             

             d.yarıçap = 7;

             d.alan = pi * d.yarıçap * d.yarıçap;

             d.çevre = 2 * pi * d.yarıçap;

 

             System.out.println ("Dairenin Alanı   : " + d.alan);

             System.out.println ("Dairenin Çevresi : " + d.çevre);

       }     

}

Alıştırmalar :    

5.       Yukarıdaki Daire3 sınıfı, Daire2 sınıfının yaptığı işin aynısını yapmaktadır. Başka bir deyişle 6-ıncı satırda öntanımlı kurucunun apaçık kullanılmasıyla yaratılan nesne ve onu işaret eden  d  referansı öncekinden daha işlevsel değildir. Bu nedenle, öntanımlı kurucuyu bu biçimde kullanmanın bir yararı yoktur. Bunu görmek için, aşağıdaki Daire4 sınıfını derleyip koşturunuz.

 

Örnek 3b:     Aşağıdaki sınıf Daire3b sınıfı, yukarıdaki Daire3a  sınıfı ile aynı işleve sahiptir.

class Daire3b {

             static int yarıçap;

              static double çevre;

             static double alan;

             final static double pi = 3.14;

  public static void main (String args[]) {

             // öntanımlı kurucu nesne yaratıyor

       Daire3b d = new Daire3b();             

             yarıçap = 7;

             alan    = pi * yarıçap * yarıçap;

             çevre   = 2 * pi * yarıçap;

 

             System.out.println ("Dairenin Alanı   : " + alan);

             System.out.println ("Dairenin Çevresi : " + çevre);

       }     

}

Alıştırmalar :    

6.       Görüldüğü gibi, öntanımlı  kurucu kullanılarak yaratılan nesneyi işaret eden  d  referansı (pointeri) kullanılmadan da, nesneye ait değişkenlere erişilebilmektedir. Sizce, bunun nedeni nedir? Değişkenlerin static olması mıdır? Programı derleyip koşturunuz.

7.       Yukarıdaki Daire4 sınıfında değişkenlerin önündeki static nitelemlerini silip, sınıfı derlemeyi deneyiniz. Oluşan hatanın nedenini açıklayınız. 

 

Örnek 3c:             Aşağıdaki sınıf Daire3c sınıfı, yukarıdaki Daire3b ve Daire3a  sınıfı ile aynı işleve sahiptir. Bu sınıfta  Daire3c d = new Daire3c();  deyimi kullanılmadığı halde, öntanımlı  kurucu kendiliğinden bellekte bir nesne yaratmıştır. Bu nesnenin static değişkenlerine main() metodu erişebilir. Kurucu metodu tanımlanmadığı ya da apaçık kullanılmadığı zaman öntanımlı kurucu kendiliğinden nesneyi yaratır.

class Daire3c {

             static int yarıçap;

             static double çevre;

             static double alan;

             final static double pi = 3.14;

  public static void main (String args[]) {

             // öntanımlı kurucu nesneyi otomatik olarak yarattı

             yarıçap = 7;

             alan = pi * yarıçap * yarıçap;

             çevre = 2 * pi * yarıçap;

 

             System.out.println ("Dairenin Alanı   : " + alan);

             System.out.println ("Dairenin Çevresi : " + çevre);

       }     

}

 

Alıştırmalar :    

8.       Öntanımlı kurucu’un otomatik olarak yarattığı nesne için bellekte bir yer ayrılmıştır. main() metodu onun static değişkenlerine erişebilir, ama anlık (instant) değişkenlerine erişemez. Böyle olduğunu görmek için değişkenlerin önündeki static nitelemini kaldırıp sınıfı derlemeyi deneyiniz. 

 

Örnek 4a:        Aşağıdaki sınıf öntanımlı  kurucu ile yaratılan iki nesne yardımıyla iki dairenin alanını ve çevresini bulmaktadır. Bu örnek programda gereksiz kod tekrarına örnektir. Programcı bundan sakınmalıdır. Sonraki örneklerde bu programı adım adım iyileştireceğiz.

 

/**

 *Bu sınıf farklı iki dairenin alan ve çevrelerini

 *bulmak için aynı kodlar

 *yinelemektedir.

 *Dolayısıyla programcılıkta tercih edilmez.

 *Bunu sonraki iki programda iyileştirmeye çalışacağız.

 */

 

 

class Daire4a {

            int yarıçap;

            double çevre;

            double alan;

            final static double pi = 3.14;

 

 

  public static void main (String args[]) {

 

      // öntanımlı kurucu ilk nesneyi yaratıyor

      Daire4a  d1 = new Daire4a();            

d1.yarıçap = 7;

            d1.alan    = pi * d1.yarıçap * d1.yarıçap ;

            d1.çevre   = 2 * pi * d1.yarıçap ;

 

System.out.println ("ilk Dairenin Yarıçapi: " + d1.yarıçap);

System.out.println ("ilk Dairenin Alanı   : " + d1.alan);

System.out.println ("ilk Dairenin Çevresi : " + d1.çevre);

            System.out.println();

 

// öntanımlı kurucu ikinci nesneyi yaratıyor

      Daire4a d2 = new Daire4a();             

d2.yarıçap = 9;

            d2.alan    = pi * d2.yarıçap * d2.yarıçap ;

            d2.çevre   = 2 * pi * d2.yarıçap ;

           

System.out.println ("ilk Dairenin Yarıçapi: " + d2.yarıçap);    

System.out.println ("ilk Dairenin Alanı   : " + d2.alan);

System.out.println ("ilk Dairenin Çevresi : " + d2.çevre);

                      

      }    

}

 

 

Alıştırmalar :    

9.     Programda main() metodu içinde 9-16 satırları ile 19-24 satırları arasında aynı kodların tekrar ettiğine dikkat ediniz. İyi bir programcı, böyle kod tekrarını önlemelidir. Bunun için ne yapmayı düşünürsünüz?

 

 

Örnek 4b.        Aşağıdaki sınıf öntanımlı (default) kurucu yerine bir aşkın (overload) kurucu tanımlamaktadır.  main() içinde aynı kurucu metodu ile iki farklı nesne yaratılmaktadır. Bunlardan birisinin yarıçapı 7 ötekinin 9 dur. Her ikisine de ana bellekte birbirlerinden farklı birer yer ayrılır.

 

class Daire4b {

       static int yarıçap;

       static double çevre;

       static double alan;

       final static double pi = 3.14;

 

             // Kurucu metodunun tanımı

       public Daire4b( int r ){

               yarıçap = r ;

             };

 

  public static void main (String args[]) {

 

       Daire4b d1 = new Daire4b(7);      //Birinci nesneyi yaratıyor

       D1.alan    = pi * yarıçap * yarıçap;

       D1.çevre   = 2 * pi * yarıçap;

 

       System.out.println ("ilk Dairenin Yarıçapi : " + d1.yarıçap);

       System.out.println ("ilk Dairenin Alanı    : " + d1.alan);

       System.out.println ("ilk Dairenin Çevresi  : " + d1.çevre);

       System.out.println();

 

       Daire4b d2 = new Daire4b(9);      //İkinci nesneyi yaratıyor

       d2.alan = pi * yarıçap * yarıçap;

       d2.çevre = 2 * pi * yarıçap;

 

System.out.println ("ikinci Dairenin Yarıçapi : " + d1.yarıçap);

       System.out.println ("ikinci Dairenin Alanı    : " + d2.alan);

       System.out.println ("ikinci Dairenin Çevresi  : " + d2.çevre);

       System.out.println();

            

       System.out.println ("ilk Dairenin Yarıçapi : " + d1.yarıçap);

       System.out.println ("ilk Dairenin Alanı    : " + d1.alan);

       System.out.println ("ilk Dairenin Çevresi  : " + d1.çevre);

       System.out.println();

       }     

}

Bu programın çıktısı şöyle olacaktır.

ilk Dairenin Yarıçapi     : 7

ilk Dairenin Alanı        : 153.86

ilk Dairenin Çevresi is   : 43.96

 

ikinci Dairenin Yarıçapi  : 9

ikinci Dairenin Alanı     : 254.34

ikinci Dairenin Çevresi   : 56.52

 

ilk Dairenin Yarıçapi     : 9

ilk Dairenin Alanı        : 254.34

ilk Dairenin Çevresi      : 56.52

Burada şaşırtıcı gibi görünen şey şudur: Yüzeysel bakışla, ilk üç satır ile son üç satırın aynı olması beklenirdi.  Ama son üç satır, beklenenin aksine ikinci dairenin yarıçapını, alanını ve çevresini vermektedir. Bu, aslında static değişken ile anlık (instant) değişken arasındaki önemli farkı göstermektedir. Bir static değişkene ana bellekte bir tek yer ayrılır, başka kopyası yaratılamaz demiştik. Programında main()’in ilk kısmı çalışınca ilk dairenin yarıçapı, alanı ve çevresinin değerleri, kendileri için ayrılan static değişkenlerin adreslerine girmiş ve bu değişkenler şu değerleri almışlardır:

yarıçap      = 7

alan         = 153.86

çevre        = 43.96 

Programda main()’in ikinci kısmı çalışınca ikinci dairenin yarıçapı, alanı ve çevresinin değerleri, birer tane olarak yaratılan static değişkenlerin adreslerine girecektir. Dolayısıyla, bu adreslerdeki ilk değerleri silinecek ve o adreslere yeni değerler yazılacaktır. Böylece, static değişkenlerin adreslerindeki yeni değerler şunlar olacaktır:

çevre        = 56.52

yarıçap      = 9 

alan         = 254.34

Her ne kadar, biz, programın üçüncü kısmında

        System.out.println ("Dairenin Yarıçapi : " +d1.yarıçap);

        System.out.println ("Dairenin Alanı    : " +d1.alan);

        System.out.println ("Dairenin Çevresi  : " + d1.çevre);

yazarak ilk daireye ait verileri yazdırmak istemiş isek de, sistem bu değerleri bulmak için yarıçap, alan ve çevre adlı statik değişkenlerin adreslerine bakmakta ve orada yazılı olan değerleri alıp ekrana vermektedir. Elbette bizim ne istediğimizi sistemin bilmesine olanak yoktur. Bellekte ne varsa onu verecektir. Kaldı ki, ilk daireye ait veriler bellekten silinmiştir, onlara erişme olanağı kalmamıştır.

 

Alıştırmalar :    

10.   Kurucu farklı değerlerle çağırmayı deneyiniz. Çıkan sonuçları çözümleyiniz.

11.   Yukarıdaki programın benzerlerini yazınız. Yazdığınız programları çözümleyiniz (her satırın ne iş yaptığını açıklayınız).

 

Örnek 4c:         Daire4b  sınıfındaki statik değişkenleri kullandığımızda, farklı iki nesne yaratsak bile, bellekte dairelerin yarıçap, alan ve çevre değerlerini ana bellekte aynı anda tutamıyorduk. Çünkü bu değişkenlere ana bellekte yalnızca birer tane yer ayrılıyor, kopyaları yapılamıyordu. Dolayısıyla, statik değişkenler, ancak son girilen değerleri tutabiliyordu. Bu durum bazı durumlarda iyidir; ama bazı durumlarda da farklı nesnelere ait olan aynı adlı değişken değerlerinin bellekte aynı anda tutulmasını isteriz. Bunun için, statik değişken yerine anlık değişken (instant variable) kullanmalıyız. Yaratılan her nesnede anlık değişkenlerin birer kopyası yer alır. Farklı nesnelerdeki aynı adlı anlık değişkenlere (kopyalar) farklı değerler girilebilir. Bu farklı değerler, nesne varlığını sürdürdüğü sürece erişilebilir değerlerdir. Aşağıdaki Daire4c sınıfı üç tane anlık değişkene, bir tane final damgalı statik değişkene, iki metot ile bir kurucua sahiptir.  

Bu program isteneni yapmakla birlikte, tolerans gösterilemeyecek kadar kod tekrarına sahiptir. İleride bunu daha kısa ve daha zarif bir biçime sokacağız.

 

class Daire4c {

            int yarıçap;

            double çevre;

            double alan;

            final static double pi = 3.14;

           

     double alanBul(){

                  alan = pi * yarıçap * yarıçap ;

                  return alan ;

            };

           

     double çevreBul(){

                  return 2 * pi * yarıçap ;

            };

 

                  // kurucu metodu

     public Daire4c(int rad){

            yarıçap=rad;

     }

           

     public static void main (String args[]) {

            Daire4c c1 = new Daire4c(7);      // nesne yaratılıyor

            System.out.println ("ilk Dairenin Yarıçapi : " + c1.yarıçap);     

            System.out.println("ilk Dairenin Alanı     : " + c1.alanBul());

            System.out.println("ilk Dairenin Alanı     : " + c1.çevreBul());

            System.out.println();

           

            Daire4c c2 = new Daire4c(9);      // nesne yaratılıyor

            System.out.println("ikinci Dairenin Yarıçapi: " + c2.yarıçap);                 System.out.println("ikinci Dairenin Alanı   : " + c2.alanBul());

            System.out.println("ikinci Dairenin Çevresi : " + c2.çevreBul());

            System.out.println();            

 

            System.out.println ("ilk Dairenin Yarıçapi : " + c1.yarıçap);                  System.out.println("ilk Dairenin Alanı     : " + c1.alanBul());

            System.out.println("ilk Dairenin Alanı     : " + c1.çevreBul());

            System.out.println();

                        

     }     

}

Bu programın çıktısı şudur:

ilk Dairenin Yarıçapi        : 7

ilk Dairenin Alanı           : 153.86

ilk Dairenin Alanı           : 43.96

 

ikinci Dairenin Yarıçapi     : 9

ikinci Dairenin Alanı       : 254.34

ikinci Dairenin Çevresi      : 56.52

 

ilk Dairenin Yarıçapi        : 7

ilk Dairenin Alanı           : 153.86

ilk Dairenin Alanı           : 43.96

 

Alıştırmalar :    

12.   Görüldüğü gibi, bu kez, Daire4c  sınıfı Daire4b sınıfında karşılaştığımız problemi yoketmiştir. Anlık değişkenlerin her birinin birer kopyası nesnelerde vardır ve nesneler bellekte kaldığı sürece onlara erişebiliriz.

13.   Kurucuu farklı değerlerle çağırmayı deneyiniz. Çıkan sonuçları çözümleyiniz.

14.   Yukarıdaki programın benzerlerini yazınız. Yazdığınız programları çözümleyiniz (her satırın ne iş yaptığını açıklayınız).

 

Görüldüğü gibi, bu kez, Daire4c  sınıfı Daire4b sınıfında karşılaştığımız problemi yoketmiştir. Anlık değişkenlerin her birinin birer kopyası nesnelerde vardır ve nesneler bellekte kaldığı sürece onlara erişebiliriz.

 

 

 

 Örnek 4d:       Aşağıdaki sınıf öntanımlı (default) kurucu yerine bir aşkın (overload) kurucu tanımlamaktadır. 6-ıncı satırda tanımlanan kurucu metodu öntanımlı kurucuu yokedip, onun yerine geçmiştir.  14-üncü ve 18-inci satırlarlarda, kurucu  sınıfa ait iki nesne yaratmaktadır. Bu nesnelerin ilkinin adresini d1 referansı , ikincinin adresini d2 referansı göstermektedir. İlk nesne yaratılırken, kurucuun r formal parametresi yerine 7 gerçek değeri konulmuştur. Böylece, yaratılan ilk nesnede dairenin yarıçapı 7 olmaktadır.  İkinci nesne yaratılırken, kurucuun r formal parametresi yerine 9 gerçek değeri konulmuştur. Böylece, yaratılan nesnede dairenin yarıçapı  9 olmaktadır.  Tabii, her birinin alanı ve çevresi bu yarıçaplara uyan değerler alacaktır.

 

class Daire4d {

            int yarıçap;

            double çevre;

            double alan;

            final static double pi = 3.14;

           

                  // Kurucu metodu

            public Daire4d( int r )

                  {

                         yarıçap = r ;

                         alan = pi * r * r;

                         çevre = 2 * pi * r;                           

                  };

 

  public static void main (String args[]) {

     Daire4d d1 = new Daire4d(7);            // nesne yaratılıyor

            System.out.println ("Dairenin Alanı    : " + d1.alan);

            System.out.println ("Dairenin Çevresi  : " + d1.çevre);

            System.out.println();

           

     Daire4d d2 = new Daire4d(9);            // nesne yaratılıyor

 

            System.out.println ("Dairenin Alanı   : " + d2.alan);

            System.out.println ("Dairenin Çevresi : " + d2.çevre);

     }     

}

Alıştırmalar :    

15.   Yukarıdaki programda bir öncekinde olduğu gibi değişken adını yazıp karşısına bir değer giremezsiniz. Örneğin, 15-inci satırdaki d1.alan yerine alan yazarsanız derleme hatası oluşur.  nci satır yerine  yarıçap = 7; yazıp programı derlerseniz, derleme hatası oluşur. Bunun nedeni, değişkenin static olmayışıdır. d1 ve d2  referanslarının işaret ettiği nesnelerin her birinde anlık değişkenler için birer yer ayrılmıştır. Bu adreslere veri girmek için referansın (pointer) hangi nesneyi işaret ettiğinin bilinmesi gerekir.

16.   Ana bellekte kurucuun yarattığı bir nesneye erişmek için, onu işaret eden bir referansa (pointer) gerekseme vardır. İlk nesnenin referansı adı  d1 ‘dir. Bu referans kullanılmazsa, sistem bu nesne içindeki alan değişkeninin bellekteki adresini bulamaz. Bunun için d1.alan yazıyoruz. yarıçap ve çevre değişkenleri için de aynı şeyler geçerlidir.

17.   Aşkın (overload) kurucuun tanımında Daire4d sınıfının anlık değişkenlerine değer girecek kodlar yazılmıştır. Dolayısıyla r formal parametresi yerine gerçek 7 değeri girilerek kurucu çağrılınca, yarıçapı 7 olan daireye ait nesne bellekte yaratılır. Nesne yaratılınca, nesneye ait alan ve çevre değişkenlerinin değerleri, kurucu tanımında yazılan formüllere göre hesaplanıp nesnedeki adreslerine yazılmış olmaktadır.

18.   Sınıf içinde öntanımlı kurucuu aşan (overload) bir kurucu daima sınıfın adını alır. Başka ad verdiğinizde, derleme hatası oluşacağını görünüz.

19.   Kurucu bir metot olduğundan, overload yaparken formal parametreler kullanabiliriz. Bu formal parametreler, sınıf tanımındaki parametrelerin tipinden olmalıdır. 6-ncı satırdaki Daire4d(int r) kurucu metodunun formal parametresi int türünden r değişkenidir. 7-inci satır, kurucu çağrılırken r ye verilecek gerçek değerin, sınıfın bir yerel değişkeni olan yarıçap adlı değişkene aktarılacağını söylemektedir. Nitekim, 10-uncu satırda kurucu çağrılırken bu parametreye 5 gerçek değeri verilmektedir. Böylece, sınıftan türetilen nesnede dairenin yarıçapı 5 olmaktadır. Öteki değişkenlerin değerleri 11-inci ve 12-inci satırlarda hesaplanmaktadır. 

20.   Kurucuu farklı sayılar yazarak çağırmayı deneyiniz. Her seferinde farklı çemberlerin alan ve çevresinin bulunduğunu görünüz.

 

Örnek 4e.         Aşağıdaki sınıf yukarıdaki ile aynıdır. Ancak çıktıları yazdırmak için kodları tekrar etmek yerine, onları yaz() metodu ile yazmaktadır. yaz() metodunun formal parametresinin Daire4e  sınıfı olduğuna dikkat ediniz.

class Daire4e {

         int yarıçap;

         double çevre;

         double alan;

         final static double pi = 3.14;

 

               // Yazdırma metodunun tanımı

         void yaz(Daire4e d){

           System.out.println ("Dairenin Yarıçapi   : " + d.yarıçap);

           System.out.println ("Dairenin Alanı      : " + d.alan);

           System.out.println ("Dairenin Çevresi    : " + d.çevre);

           System.out.println();           

         } ;

 

               // Aşkın Kurucu metodunun tanımı

         public Daire4e( int r )

               {

                    yarıçap = r ;

                    alan    = pi * r * r;

                    çevre   = 2 * pi * r;                   

               };

 

  public static void main (String args[]) {

       Daire4e d1 = new Daire4e(7);   // nesne yaratılıyor

               d1.yaz(d1);             // yaz metodu çağrılıyor

        

       Daire4e d2 = new Daire4e(9);   // nesne yaratılıyor

               d1.yaz(d2);             // yaz metodu çağrılıyor

    }   

}

 

Alıştırmalar :    

21.    Yukarıdaki programda d1.yaz(d1); yerine  yaz(d1); yazıp derleyiniz. Derleme hatasının neden oluştuğunu açıklayınız.

22.    Static main() metodu anlık (instant) yaz() metodunu çağıramadığına göre, yaz() metodunu static yaparak programı derleyiniz. Bu kez hata oluşmadığını gördünüz mü?

 

 

Özet

1.  Sınıf bir tür adıdır (cins-isim). Sınıf tanımı içinde yer alan değişken ve metotlar ancak bir nesne içinde hayat bulur.

2.  Aksi istenmezse, sınıf derlenince ana bellekte onun bir öğesi yaratılır. Yani o türden bir nesne oluşturulur ve ana bellekte ona bir yer ayrılır. O nesne ile sınıfın belirlediği işler yapılabilir. Bu işi yapan öntanımlı (default) bir metot vardır. Buna kurucu (kurucu) metodu denir.

3.  Programcı isterse öntanımlı kurucuu apaçık biçimde çağırabilir. Bu durumda metodun parametre girilmez. Yalnızca Sınıf_adı referans_adı = new Sınıf_adı();  yazılır. Bu yapıldığında, nesneye referans_adı ile erişilir. Böyle yapıldığında, bellekte bir tek nesne oluşur. Ona ait değişkenler ancak son girilen değerleri tutabilir.

4.  Programcı isterse öntanımlı kurucuu yokeden aşkın (overload) kurucu tanımlayabilir. Bu durumda, metot tanımında enaz sınıfın bir değişkeni parametre olarak belirlenmelidir. Bu parametre(ler)e verilecek gerçek değer(ler) ile çağrılan kurucu, her çağrılışta bellekte ayrı bir nesne yaratır. Her nesnenin anlık (instant) değişkenleri birbirlerinden farklı değerler alabilir ve bellekte kaldıkları sürece bu değerleri tutarlar.

5.  Statik değişkenlere ana bellekte bir tek yer ayrılır, kopyaları oluşamaz. Dolayısıyla, farklı nesneler yaratılsa bile, bir statik değişenin bir tek değeri olur; her nesne bu değeri kullanır. Tabii, program koşarken statik değişkenin değeri, istenirse değiştirilebilir. Ama, daima son girilen değeri tutar, öncekiler ebediyen silinir.

6.  Aynı adla ancak bir tane statik metot olabilir. Bir statik metodun kopyası olamaz. Static metotlar ancak statik değişkenlere ve başka statik metotlara erişebilir.

7.  Nesnelerden oluşan bir array tanımında öntanımlı kurucu oluşmaz; çünkü array adı nesneleri işaret eden referanstır, nesnenin kendisi değildir.

8.  Kurucular this() metodunu kullanarak birbirlerini çağırabilirler.

9.  Öntanımlı kurucu kesinlikle gerekli değilse tanımlanmamalıdır.

10.   Öntanımlı kurucu yerine aşkın yükleme (overload) yapılarak bir kurucu tanımlanmak istenirse, sözdizimi şöyledir:

public sınıf_adı (formal parametreler listesi)

{

    bildirgeler

    deyimler

}

Kurucu bir nesneyi yaratınca şu işler gerçekleşir:

·         Kurucu daima public erişim belirtkesini alır. Böyle olmazsa, yarattığı nesneye dışarıdan erişmek mümkün olamaz.

·         Kurucu’un adı sınıfın adıdır.

·         Normal halde, costructor metodu çağrılırken new anahtar sözcüğü ile kullanılır.

·         Kurucu ana bellekte nesneye bir yer ayrılmasını sağlar.

·         Kurucu her çağrılışında yeni bir nesne yaratır.

·         Sınıf değişkenleri ve metotlar bütün nesnelerde aynıdır, değiştirilemez. 

·         Anlık değişken ve metotlar farklı nesnelerde farklı olabilir.

Örnek:

Public class Havuz

{

          

//Anlık değişkenler

           private float havuzBoyu ;

           private float havuzEni ;

           private float minDerinlik;

           private float maxDerinlik;

}

Şimdi bir kurucu metodu yazalım.

Public Havuz ( float uzunluk,

                                  float en,

                                  float  azDerinlik,

                                  float  cokDerinlik,

                                                  )      

{

          

           havuzBoyu          =  uzunluk;

           havuzEni              = en;

           minDerinlik          = azDerinlik;

           maxDerinlik         = cokDerinlik;

}

Formal parametrelerine farklı gerçek değerler vererek kurucuu çağırabiliriz. Kurucu her çağrılışında farklı bir nesne yaratır. Böylece istediğimiz sayıda nesne yaratabiliriz. Yukarıdaki kurucuu çağıran sözdizimi şöyledir:

Havuz  ilkHavuz = new Havuz ( 100.0f ,30.0f , 3.0f , 8.0f ) ;

Kurucu ana bellekte Havuz için bir nesne yaratmıştır. Bu nesnenin anlık değişkenleri şu değerleri almıştır:

           havuzBoyu          =  100.0f ;

           havuzEni              =  30.0f ;

           minDerinlik          =  3.0f ;

           maxDerinlik         =  8.0f ;

Formal parametrelerine gerçek değerler atayarak bir metodu çağırırken şunlara dikkat etmeliyiz:

11.   Formal parametre sayısı kadar gerçek parametre girilmelidir.

12.   Gerçek parametreler, formal parametrelerin yazıldığı sırada girilmelidir.

13.   Gerçek parametrelerin tipleri ile formal parametrelerin tipleri (karşılıklı) aynı olmalıdır.

 

 

Örnekler

public class Spot {

    public int size;

    public int x, y;

 

    public Spot(int intSize) {

        size = intSize;

        x = -1;

        y = -1;

    }

}

 

Static değişken

class PersonelData {

static String ad;

static int sene; 

}

 

Anlık değişken

class OgrenciData {

String ad;

int sene;

}