Yazan : Şadi Evren ŞEKER

Nesne yönelimli programlama dillerinde, sınıflar (class) arasında miras ilişkisi bulunması halinde (inheritance), bu sınıflardan türetilen nesnelerin birbirine akıtılması durumudur.

Bu durumu aşağıdaki örnekler üzerinden anlamaya çalışalım:

public class insan{
   int boy;
   int kilo;
}
public class öğrenci extends insan{
   int sınıf;
   String bölüm;
}

Örnek olarak verilen yukarıdaki iki sınıf arasında miras ilişkisi bulunmaktadır ve insan sınıfı, öğrenci sınıfının atası olarak kabul edilebilir.

Şimdi bu sınıflardan birer nesne tanımlayarak akış işlemini göstermeye çalışalım:

public class test{
   public static void main(String args[]){
      öğrenci ali = new öğrenci();
      insan veli = new insan();
      ali= veli;
      veli = new öğrenci();
   }
}

Yukarıdaki kodun son iki satırında bulunan atama işlemleri birer akış işlemidir (casting) ve ali=veli atamasında, öğrenci tipinden bir nesne atfına, insan sınıfından bir nesne konulduğu için bu akışa, aşağı akış (down casting) ismi verilir.

Bu akışın tam ters yönlüsü olan ve son satırda yer alan atamada ise veli isimli insan tipinden bir nesne atıfının içerisine öğrenci sınıfından bir nesne yerleştirilmektedir. Bu durum ise yukarı akış (up casting) olarak isimlendirilmektedir.

Klasik olarak nesne yönelimli programlama dillerinde aşağı akış (downcasting) yapılması halinde, nesnenin bütün bilgilerine erişilebilirken, yukarı akış (upcasting) yapılması durumunda nesnenin sadece nesne atfının üyeleri kadar bilgisine erişilebilir. Örneğin yukarıdaki kod için veli isimli değişken, insan tipinde olduğu için, öğrencinin boy ve kilosuna erişebilirken, öğrencinin sınıfı veya bölümüne erişemez. Bu bilgiler daha önceden atanmışsa hafızada durur ama erişilemez. Tekrar öğrenci tipinde bir nesne atıfı tarafından karşılanması durumunda bu bilgilere erişilebilir. Örneği yukarıdaki kodun sonuna aşağıdaki satır eklenseydi:

ali = veli;

Bu durumda veli tarafından atıfta bulunulan öğrenci, kendi tipinden bir nesne atıfı tarafından gösterilecek ve veli tarafından erişilemeyen değerlere erişilebilecekti.

Atama işlemleri sırasında unutulmaması gereken bir husus da, tip inkılabında olduğu gibi (type casting) aşağı akış sırasında (downcasting) mutlaka tip dönüşümü yapılması gerektiğidir. Örneğin yukarıdaki kodda bulunan bu satır JAVA dili açısından hatalıdır:

ali= veli;

Ancak bunun tam tersi atama hatalı değildir:

veli = ali;

Yukarıdaki hatalı olan atamayı düzeltmek için tip dönüşümü yapılabilir:

ali = (öğrenci) veli;

şeklinde.

Yorumlar

  1. comen

    İyi günler hocam,
    Aşağıdaki kodda bir noktayı anlamadım

    
    class Asker{     
    int x=10;
     public void selamVer(){
         System.out.println("Asker selam verdi");
     }  
    }
    class Er extends Asker{
        int x = 20;
        public void selamVer(){
         System.out.println("Er selam verdi");
     }     
    }
    public class Deneme {
        public static void main(String[] args) {
            Asker a = new Asker();
            Er e = new Er();
            Asker ae = new Er();
            a.selamVer();
            e.selamVer();
            ae.selamVer();
            System.out.println(a.x+" "+e.x+" "+ae.x);
        }
    }
    

    Asker selam verdi
    Er selam verdi
    Er selam verdi
    10 20 10
    Bu şekilde sonuç veriyor. Burada anlamadığım nokta Asker ae = new Er(); kısmında up casting olduğu için Asker sınıfının Er sınıfı içindeki nesnelere de erişebileceğini göstermez mi ? Bu yüzden son satırın 10 20 20 şeklinde olması gerekmiyor muydu?

  2. Şadi Evren ŞEKER Article Author

    Gerekmiyor çünkü JAVA hata yapmaz 🙂

    Öncelikle güzel bir soru sormuşsunuz bunu belirtmek isterim, bu konu çoğu kişinin ilk başta karıştırdığı bir nokta.

    Probleminiz çok basitçe iki kavramı karıştırıyor olmanız. Overriding (üzerine yükleme) ile değişkenlerin geçerlilik alanı (scope of variable) aynı şey değildir.

    selamVer() fonksiyonu için yukarıda bir üzerine yükleme yapılmış ve sizin de örneğinizde olduğu gibi yeni yüklenen Er sınıfındaki çalışıyor.

    Ancak değişken geçerliliğine gelince kimin eriştiği önemlidir. Object referrer (nesne atıfı) şayet asker ise askerin değişkenine erişilecektir.

    Daha iyi anlatmak için şöyle söyliyeyim.

    Er sınıfında tek bir selamVer fonksiyonu tanımlıdır o da er sınıfında tanımlı olandır. Asker sınıfındaki tanımı yok edip yeniden tanımlanmıştır.

    Ancak er sınıfında tek bir x değişkeni tanımlıdır denemez!! Er sınıfında hem burada tanımlanan x değişkeni vardır hem de askerde tanımlı olan x değişkeni vardır. Siz hangi değişkene erişirseniz onu çalıştırırsınız.

    Daha da basitleştirmek için şunu söyleyebiliriz. fonksiyonlar yer kaplamaz, değer almaz ama değişkenler yer kaplar ve değer alır. Dolayısıyla sınıf tanımında bulunan bu değişkenler değer alırlar ve aynı anda ikisi de tanımlı ve yer kaplayan değerlerdir, siz kimden erişirseniz onun değerini okursunuz.

  3. comen2

    merhabalar hocam

    kod a soyle bir satır eklediğimizde
    Er d =(Er) new Asker(); // unused assignment uyarısı veriyor

    d nin değişken ve fonksiyonlarına ulaşılmıyor
    d.x ; ve d.selamVer(); satırları hata veriyor

    bunun sebibi nedir ve sorun nasıl cözülür ?

  4. Şadi Evren ŞEKER Article Author

    Evet hata verir. JAVA’da downcasting (Aşağı akış) sadece uygun tipler arasında yapılabilir. Sizin örneğiniz JAVA için hatadır. Daha büyük bir nesneyi gösterme yeteneği olan ER sınıfının içine daha küçük bir nesne koyarsanız bu büyük nesnenin özelliklerine ve fonksiyonlarına erişilemeyeceği için java çalışma zamanında (runtime) hata verir.

    Şayet illaki downcasting yapmak istiyorsanız aşağıdaki gibi bir örnek yapılabilir:

    Er e = new Er();
    Asker a = e; // burada upcasting yaptık
    Er d = (Er) a; // burada downcasting yaptık ve hata vermez çünkü zaten yeteneğimiz dahilinde bir obje

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir