KALITIM

(Inheritance)

Java’da kalıtım nedir?

Nesne Yönelimli Programlama dillerinde kalıtım olgusu, bir sınıfta (class) tanımlanmış değişkenlerin ve/veya metotların (fonksiyon, procedure) yeniden tanımlanmasına gerek olmaksızın yeni bir sınıfa taşınabilmesidir. Bunun için yapılan iş, bir sınıftan bir alt-sınıf (subclass) türetmektir. Türetilen alt-sınıf, üst-sınıfta tanımlı olan bütün değişkenlere ve metotlara sahip olur. Bu özeliğe kalıtım özeliği (inheritance) diyoruz.

Programcı, yeni alt-sınıfları tanımlarken, üst-sınıftan (superclass) kalıtsal olarak geleceklere ek olarak, kendisine gerekli olan başka değişken ve metotları da tanımlayabilir.

Bu yolla, bir kez kurulmuş olan sınıfın tekrar tekrar kullanılması olanaklı olur. Böylece, programlar daha kısa olur, programın yazılma zamanı azalır ve gerektiğinde değiştirilmesi ve onarılması (debug) kolay olur.

Alt-sınıf türetme hiyerarşik bir yapıda olur. Bir alt-sınıfın türetildiği sınıf, o alt-sınıfın üst-sınıfıdır. Java’da bir alt-sınıfın ancak bir tane üst-sınıfı olabilir (C++ ‘dakinden farklı olduğuna dikkat ediniz). Ama bir sınıftan birden çok alt-sınıf türetilebilir.

Üst-sınıfa ata (parent), alt-sınıfa da oğul (child) denir.

Örnekler

Liste 1:   Ön-tanımlı (default) belirtkeli sınıfta kalıtım

Liste 1 içindeki sınıflar kalıtımın basit bir örneğidir. B sınıfı A sınıfının bir alt-sınıfıdır. A sınıfının erişim belirtkesi olmadığından, ön-tanımlı (default) belirtke etkindir. Dolayısıyla, A sınıfının değişkenlerini ve metodunu B sınıfı kullanabilir.

/* A sınıfının değişken ve metodu B ye

 * kalıtımsal geçecektir.

*/ Üst sınıf tanımlanıyor.

class A {

  int i, j;

 

  void showij() {

    System.out.println("i and j: " + i + " " + j);

  }

}

 

 

// A ‘nın B alt-sınıfı tanımlanıyor.

class B extends A {

  int k;

 

  void showk() {

    System.out.println("k: " + k);

  }

  void sum() {

    System.out.println("i+j+k: " + (i+j+k));

  }

}

 

 

// Uygulama programı

// A ve B sınıflarına ait nesneler yaratılıyor.

// A ve B ile aynı pakette (aynı dizinde) bulunmalıdır.

class BasitInheritance {

  public static void main(String args[]) {

    A ustOb = new A();      // A ‘ya ait nesne

    B altOb = new B();      // B ’ye ait nesne

 

    // Anlık değişkenlere atama yapılıyor.

    ustOb.i = 15;

    ustOb.j = 25;

    System.out.println(" ustOb nesnesinin öğeleri: ");

    ustOb.showij();   //ustOb ‘nin öğelerini yazar

    System.out.println();

 

    /* Alt-sınıf üst-sınıfın bütün

     * öğelerine erişebilir.

    */

    altOb.i = 3;

    altOb.j = 5;

    altOb.k = 7;

    System.out.println("altOb nesnesinin öğeleri: ");

    altOb.showij();   //üst-sınıftaki değişkenleri yazar

    altOb.showk();    //alt-sınıftaki değişkeni yazar

    System.out.println();

 

    System.out.println("üst ve alt sınıftaki değişkenler toplanıyor… ");

   System.out.println("(i + j + k) = ");

 

    altOb.sum();

  }

}

 

 

Liste 2 :   private damgalı öğelere erişim

Üst-sınıfın private öğelerine, kendi alt sınıfı da dahil olmak üzere başka hiçbir sınıftaki kodlar erişemez. Aşağıdaki listede tanımlanan B alt-sınıfındaki kodlar, A üst-sınıfının private damgalı öğelerine erişemiyor.

 

/*

 * Üst-sınıfın private öğelerini

 * alt-sınıfın kodları kullanamaz.          

*/

 

// Üst-sınıf tanımlanıyor.

class A {

  int i;              // erişim kısıtı yok

  private int j;      // erişim kısıtlanıyor

 

  void setij(int x, int y) {

    i = x;

    j = y;

  }

}

 

    // A'nın j öğesine erişemez.

class B extends A {

  int toplam;

 

  void sum() {

    total = i + j; // HATA!, alt-sınıftaki bu kod j ye erişemez

  }

}

 

class DegerVer {

  public static void main(String args[]) {

    B subOb = new B();

 

    subOb.setij(15, 20);

 

    subOb.sum();

    System.out.println("Toplam : " + subOb.toplam);

  }

}

 

 

 

 

 

Liste 3:

Bu listede AltKutu alt-sınıfı, üst sınıfta olmayan bir değişken (agr) tanımlıyor. Bu değişken kutunun ağırlığını tutacaktır. Bir sınıf içinde parametresiz ve parametreli yapıcılar (constructor metodu) tanımlanabilir. Formal parametre(ler),  sınıfın anlık değişkenlerine değer atamak için, o tip(ler)den seçilebileceği gibi, o sınıf tipinden de olabilir. Formal parametreli bir metot çağrılırken, o parametrelere gerçek değerler verilir. Gerçek değerler, formal parametrelerle aynı tipten olmalı ve aynı sırada yazılmalıdır. Formal parametre bir sınıf tipinden ise, metot çağrılırken formal parametre yerine o sınıftan bir nesne konulur. 

 

/* Kutu – üst-sınıfının 3 tane anlık (instance)

   değişkeni var.

*/

class Kutu {

  double en;

  double boy;

  double yukseklik;

 

  // Parametreli constructor tanımı.

  // Parametre class tipinden olabilir.

  // Bu constructor Kutu’nun bir kopyasını yaratıyor.

  Kutu(Kutu ob) {     // parametre kendi sınıfının tipindendir.

    en   = ob.en;

    boy  = ob.boy;

    yukseklik   = ob.yukseklik;

  }

  // Formal parametreli constructor tanımı.

  // Constructor Kutu’nun boyutlarını belirliyor.

  Kutu(double e, double b, double y) { // boyutlar için 3 parametre

    en  = e;

    boy = b;

    yukseklik  = y;

  }

       /*

         * parametresiz constructor tanımı.

         * Henüz asıl değerlerin verilmediğini belirtmek için

         * değişkenlere -1 değeri atanıyor.

        */ 

  Kutu() {

    en  = -1;         // geçici değer

    boy = -1;         // geçici değer

    yukseklik  = -1;  // geçici değer

  }

  // Formal parametreli constructor tanımı.

  // Constructor Kutu’nun boyutlarını eşitliyor (küp oluşturuyor)

  Kutu(double uzunluk) {

    en = boy = yukseklik = uzunluk;

  }

 

  // hacim hesaplar

  double hacim() {

    return en * boy * yukseklik;

  }

}

 

  // alt-sınıf tanımı

  // Kutu’nun değişkenlerine bir ek yapılıyor (agr).

class AltKutu extends Kutu {

  double agr;               // Kutu’nun ağırlığı

 

  // AltKutu için constructor metodunun tanımı

  AltKutu(double e, double b, double y, double a) {

    en  = e;

    boy = b;

    yukseklik  = y;

    agr = a;

  }   

}

 

// Uygulama programı.

class DemoAltKutu {

  public static void main(String args[]) {

    AltKutu kutu1 = new AltKutu(15, 30, 25, 53.7);

    AltKutu kutu2 = new AltKutu(4, 5, 6, 0.123);

    double vol;

 

    vol = kutu1.hacim();

    System.out.println("kutu1 ‘in hacmi    = " + vol);

    System.out.println("kutu1 ‘in ağırlığı = " + kutu1.agr);

    System.out.println();

 

    vol = kutu2.hacim();

    System.out.println("kutu2 ‘nin hacmi    = " + vol);

    System.out.println("kutu2 ‘nin ağırlığı = " + kutu2.agr);

  }

}

 

 

Uyarı: Aşağıdaki uygulama programı üst-sınıftan bir referansa (işaretçi, pointer) alt-sınıftan bir referansın değerinin atanabileceğini göstermektedir. 3-üncü satırda yaratılan ve alt-sınıfa ait olan nesnenin bellekteki adresini altKutu1 işaretçisi göstermektedir. 4-üncü satırda yaratılan ve üst-sınıfa ait olan nesnenin bellekteki adresini ustKutu2 işaretçisi göstermektedir. 16-ıncı satırdaki ustKutu2 = altKutu1; ataması geçerlidir. Bu tür atamalar, bazen programcıya kolaylık sağlar. Burada dikkat edilmesi gereken şey şudur. Üst-sınıfa ait işaretçisine alt-sınıf işaretçisi atansa bile, üst-sınıftaki kodlar, alt-sınıftaki öğelere erişemez. Oysa slt-sınıftaki kodlar, üst-sınıfta private damgası taşımayan öğelere erişebilir.

 

       /* Bu uygulama programı referansların (işaretçi, pointer)

            kullanılışını göstermektedir. */

class UygulaPrg {

  public static void main(String args[]) {

    AltKutu altKutu1  = new AltKutu(4, 5, 6, 12.23);

    Kutu ustKutu2     = new Kutu();

    double vol;

 

    vol = altKutu1.hacim();

    System.out.println("altKutu1 in hacmi    = " + vol);

    System.out.println("altKutu1 in ağırlığı = " + altKutu1.agr);

    System.out.println();

 

    /*

       * ustKutu2 işaretçisinin gösterdiği adres

       * altKutu1 işaretçisinin gösterdiği adres ile aynı kılınıyor.

       * Aynı tipten referanslar eşitlenebibilir.

    */

    ustKutu2 = altKutu1;

 

    vol = ustKutu2.hacim(); // hacim(), Kutu ‘nun bir metodudur,

                            // dolayısyla kod geçerlidir.

    System.out.println("ustKutu2 ‘nin hacmi    = " + vol);

 

    /* Aşağıdaki kod geçersizdir, çünkü ustKutu2’nin

       agr öğesi yoktur. */

  System.out.println("ustKutu2’ın ağırlığı =  " + ustKutu2.agr);

  }

}