ÖNEMLİ : Kendim için aldığım notlar. Umarım size de bir faydası olur. Kullanılan her bir makale referans olarak eklenmiştir.

Java’da Kalıtım(inheritance) ve Java’da Polimorfizm Serisi


  1. Java’da Polimorfizm 1 - Amaç?
  2. Java’da Polimorfizm 2 - İzlenecek Kurallar Nelerdir?
  3. Java’da Polimorfizm 3 - Casting
  4. Java’da Polimorfizm 4.1 - Statik ve Dinamik Bağlanma 1
  5. Java’da Polimorfizm 4.2 - Statik ve Dinamik Bağlanma 2
  6. Java’da Polimorfizm 4.3 - Dinamik Bağlanma Örnek
  7. Java’da Polimorfizm 5 - Soyut(Abstract) Sınıflar ve Arayüzler(Interfaces)

Genel Bakış

Katıldığım online bir etkinlikte object-oriented nedir şeklinde sorulan bir soruya Robert C. Martin şu şekilde yanıt vermişti.

“A language is object-oriented if it supports dynamic polymorphism” (“Bir dil, dinamik polimorfizmi destekliyorsa nesne yönelimlidir”)

Kısa ve öz bir tanım.

Anlaşılacağı üzere polimorfizm nesne yönelimli bir dilin merkezindedir. Bu bölümde ise derleme zamanı ve çalışma zamanı kurallarına odaklanacağız. Ve bunu bir kez anladığınızda, polimorfizmin çalışma mantığını çok iyi anlayacağınızı temin ederim.

Derleyici gibi düşün, çalışma zamanı ortamı gibi davran (Rick Ord)

Bu sözün aslında altında yatan mantık çok açıktır. Çünkü bir kodu her çalıştırdığımızda gerçekleşen iki şey vardır. Birincisi, bir derleyicinin yazdığınız kodu yorumlaması gerektiğidir. İkinci şey ise, çalışma zamanı ortamı bu yorumlanan alıntıyı çalıştırır. Polimorfizm hakkında düşüneceksek şayet bunları göz önüne almamız gerekmektedir. O halde, polimorfizm söz konusu olduğunda derleme zamanı kurallarına ve çalışma zamanı kurallarına bakarak devam edelim.

Derleme Zamanı Kuralları(Compile-time Decision)

  1. Derleyici SADECE referans tipini bilir: (yani derleyici nesnenin çalışma zamanı tipini bilmez. Derleyicinin amacı, daha sonra çalışma zamanında yürütülecek olan bir yöntem imzası çıkarmaktır.)


    Java Polymorphism(java polimorfizm)

    1
    2
    
     Person s = new Student("Hasan", 1111);
     s.toString();
    

    Yukarıdaki örnekte bir adet Person, bir adet de Student sınıfımız bulunmaktadır. Görüleceği üzere Person sınıf tipinde s referansımız, Student nesnesine işaret ediyor. Planımız her ne kadar Student nesnesinde toString yöntemini çağırmak gibi görünse de(aslında bir bütün olarak baktığımızda öyle!), javanın kodu bu şekilde yorumlamadığını bilmemizde yarar var. Java kurallarını derleme ve çalışma zamanı olarak ikiye ayırır. Kurala göre de derleyicinin sadece Person referansını bildiğini unutmayalım. Yani derleme zamanında javanın bu koddan algıladığı tek şey s referansının bir Person olduğudur.

  2. Derleyici metot çağrıları için SADECE referans tipinin sınıfına bakar: s referansı ile toString‘i çağırmayı denediğinizde, java derleme zamanında ilk olarak Person sınıfına bakacak ve bu toString yöntemini bulacaktır.


    Java Polymorphism(java polimorfizm)

  3. Derleyici bir yöntem imzası yayımlar: Derleyicinin bir diğer amacı ise daha sonra çalışma zamanında yürütülecek olan bir yöntem imzası çıkarmaktır. Yani parametresiz bir toString yöntem imzası derleyici tarafından daha sonra çalışma zamanında yürütülmek üzere yayımlanır.


    Java Polymorphism(java polimorfizm)

Çalışma Zamanı Kuralları(Runtime Decision)

  1. Çalışma zamanında, ilgili yöntemi bulmak için java, nesnenin çalışma zamanı türünü izler
  2. Derleme zamanında yayımlanan yöntem imzasını gerçek çalışma zamanı sınıfındaki uygun yöntemle eşleştirir: Yukarıdaki örnekten yola çıkarsak, s.toString yapmaya çalıştığımızda java, artık çalışma zamanında s‘in aslında bir Student nesnesi olduğunu bilir ve bu metodu ilk bu sınıfın içinde arar. Yukarıdaki koddan yola çıkarsak, java Student sınıfında toString yöntemini bulacak ve çalışma zamanında çalıştıracaktır.


    Java Polymorphism(java polimorfizm)

    ÖNEMLİ NOT : Buraya kadar olanlar ilgili yöntem(yani toString metodunu kastediyorum) geçersiz kılınmışsa gerçekleşecek şeylerdir. Çünkü ilgili yöntem geçersiz kılınmışsa, polimorfizm gereği doğrudan geçersiz kılınan yöntem çalıştırılır. Yani bu örnekte yöntemin geçersiz kılındığını görüyoruz.

  3. Peki ilgili yöntem geçersiz kılınmamışsa ne olur? Bu durumda ise java çalışma zamanı sınıfında uygun bir yöntem bulamadığı için referans tipinin sınıfındaki yöntemle eşleşir. Bu kısım çok önemlidir. Farzedelim ki yukarıdaki örnek şu şekilde olsaydı(Student sınıfına odaklanmanızı istiyorum. Dikkat ederseniz toString metodu override edilmemiş)


    Java Polymorphism(java polimorfizm)

    s.toString yazarak metodu çağırmaya çalıştığımızda, Person sınıfındaki toString metodu çalışacaktır.

Aslında polimorfizm, derleme zamanı ve çalışma zamanı polimorfizmi olarak ikiye ayırabiliriz. Derleme zamanında alınan kararlar sonucu gerçekleşen bağlanmalara statik/erken bağlanma(static or early binding), çalışma zamanında alınan kararlar sonucu gerçekleşen bağlanmalara da dinamik/geç bağlanma(dynamic or late binding) denir. Bununla ilgili aslında ayrı bir bölüm açmayı planlıyorum. Çünkü burada bahsedilenlerin dışında da değineceğim bilgiler var.

Şimdi yukarıdaki kuralları düşünerek aşağıdaki soruya cevap bulmaya çalışalım.

Örnek

Bu sefer s referansı ile getSID() metoduna ulaşmaya çalışacağız. Yukarıda yazdığım için tekrardan Student ve Person sınıflarını yazma gereği duymadım. Göreceğiniz üzere bu metot Student sınıfının içinde yer almaktadır. Sizce bu kod çalışır mı?

1
2
Person s = new Student("Hasan", 1234);
s.getSID();

Aslında ilk bakışta kodun çalışacağını düşünebiliriz. Ama çalışma zamanı dışında bir de derleme zamanı kararlarına uymamız gerekmektedir. Sırayla ilerleyecek olursak kodun çalışması için ilk önce derleme zamanı kurallarını karşılaması gerekmektedir. Koda tekrar bakacak olursak, derleyici yalnızca Person içindeki yöntemleri bilecektir. Çünkü derleyiciye göre s bir Person referansıdır. Dolayısıyla, derleyici Person sınıfında getSID yöntemini bulmaya çalışacaktır. Fakat bu yöntemin Person sınıfında olmadığını biliyoruz. Bu sebepten ötürü bir derleme hatası alırız. Yani kodun çalışma zamanına geçme şansı olmayacaktır.

Yalnız koda baktığımızda bu metodun Student sınıfında bulunduğunu biliyoruz. Peki bizim bu bildiğimizi derleyicinin bilmesini nasıl sağlarız. Bunun yöntemi casting‘dir. Bir sonraki ders bu konu üzerine konuşacağız.

Özet

Java’da polimorfizm konusundan bahsederken sıklıkla derleme ve çalışma zamanı kararlarından bahsettik. Aslında polimorfizmi tanımsal olarak rahatlıkla ikiye ayırabiliriz.

  1. Statik veya derleme zamanı polimorfizmi
  2. Dinamik veya çalışma zamanı polimorfizmi

Anlaşılacağı üzere statik polimorfizm derleme zamanında gerçekleşirken, dinamik polimorfizm çalışma zamanında gerçekleşir.

Referanslar