Arayüzlerde Varsayılan Metotlar (Default Methods) – II

Bir önceki yazıda arayüzlerdeki bir gerçekleştirmeye sahip olan metotlara giriş yapmıştık.

Java SE 8 ile birlikte gelen, arayüzlerde varsayılan metot kullanımı, default method, işin içine girdikçe kafamızı karıştırmaya devam edecek gibi görünüyor. Bende hep öyle olur. Bir konuyu öğrenirken başta çok karmaşık gibi gelmez ama sıklıkla, ilerlemeyle birlikte durum çetrefilleşir ve olmadık yerlere çıkar. Bu durum tabi olarak büyük keyif verir, zekanızı zorlar, sizi düşünmeye iter ama geldiğiniz noktanın acaipliği hep aklınızda kalır.

Bakın arayüzlerde default metot kullanımının bizi getirdiği yere. Hangisinden başlayalım? Çoklu mirası (multiple inheritance) ele alalım önce.

C++’tan bilirim, eğer bir alt sınıf, aynı virtual olmayan metoda sahip iki sınıftan miras devralıp da o metodu override etmezlerse, probleminiz var demektir. Eski zamanlardan hatırladığım şey bu duruma “diamond problem” ya da “deadly diamond of death” dendiği. Java’da bir sınıftan devralma anlamında çoklu mirasa izin verilmeyişi, sadece arayüzlerden devralma anlamında çoklu mirasın söz konusu oluşu, bu problemi şu ana kadar ertelemişti. Ama arayüzlere default metot koyunca durum değişti. Bakın, Artist bir arayüzümüz ile onun alt arayüzleri olan Actor ve Musician arayüzlerimiz olsun:

package org.javaturk.oofp.ch04.multipleInheritance;

public interface Artist {
	
	void play();
}
package org.javaturk.oofp.ch04.multipleInheritance;

public interface Actor extends Artist{
	
	default void play(){
		System.out.println("Actor plays!");
	}
}
package org.javaturk.oofp.ch04.multipleInheritance;

public interface Musician extends Artist{
	
	default void play(){
		System.out.println("Musician plays!");
	}
}

Yukarıdaki henüz tamamlanmamış elması, Actor ve Musician arayüzlerininden devralan ama “play()” metoduna bir gerçekleştirme vermeyen MusicianActor sınıfı ile tamamlayalım:

package org.javaturk.oofp.ch04.multipleInheritance;

public class MusicianActor implements Actor, Musician{

}

Diamond Problem

 

 

MusicianActor‘ün araryüzünde “play()” metodu var ama hangi gerçekleştirmeye sahip? Gelinen noktada, “diamond problem” ile karşılaştık. Bu durumda MusicianActor sınıfı derlenmeyecektir. Bunu çözmenin yöntemi ise ancak MusicianActor‘ün “play()” metoduna bir gerçekleştirme vermesidir.

package org.javaturk.oofp.ch04.multipleInheritance;

public class MusicianActor implements Actor, Musician{
	
	public void play(){
		System.out.println("MusicianActor plays!");
	}
}

Dolayısıyla default metotlara sahip olmanın ilk maliyeti, diamond problemine duçar olmaktır.

Default metotlarla alakalı bir başka durum ise, üst bir arayüzün default metot tanımlamasına karşın, onun alt arayüzünün aynı metodu abstract olarak tekrar tanımlamasında oluşur. Yukarıda verdiğimiz örneği biraz değiştirerek devam edebiliriz. Bu defa Actor, play() metodunu default olarak tanımlar:

package org.javaturk.oofp.ch04.multipleInheritance.v2;

public interface Artist {
	
	default void play(){
		System.out.println("Artist plays!");
	}
}

Ve tek alt arayüzleri olarak Musician ise “play()” metodunu abstract olarak tekrar tanımlarlar:

package org.javaturk.oofp.ch04.multipleInheritance.v2;

public interface Musician extends Artist{
	
	void play();
}

Tabi olarak bu durumda, hiyerarşinin en altındaki Pianist sınıfı “play” metoduna bir gerçekleştirme sağlamak zorundadır, aksi taktirde abstract bir sınıf olur. Pianist‘i abstract yapalım:

package org.javaturk.oofp.ch04.multipleInheritance.v2;

public abstract class Pianist implements Musician{	
}

 

Garip bir hiyerarşi!

Geçmiş olsun 🙂 Herkese iyi günler dileriiim, iyi hafta sonlarııııı 🙂

Üst arayüz Artist ile Musician ve Pianist arasındaki ilişkiye bir bakın. Farkedebildiniz mi?

Gariplik şurada: “interface” anahtar kelimesiyle oluşturduğumuz arayüzler, bir önceki yazıda da vurguladığım gibi sadece davranışların tanıtımının (declaration) yapıldığı yerlerdir. Davranışların tam olarak tanımlandığı (definition) yer değildir, davranışlar arayüzlerde tanıtılır, sınıflarda tanımlanır. Bu yüzden bu yapılara, sadece arayüz sağladığı için “arayüz” ya da “interface” denir. Ama yukarıdaki durumda tanımlamayı yapan arayüzdür, tanıtımı yapan ise sınıf! “play()” metodu Artist arayüzünde tam olarak tanımlanıyor ama hiyerarşinin en altındaki Pianist sınıfı ise aynı davranışı tanıtıyor, yani üst tipi olan Mucisian arayüzünden abstract olarak devralıyor ama bir gerçekleştirme vermiyor.

Ne demiş atalarımız böyle durumlarda: “Ne oldum demeyeceksin, ne olacağım diyeceksin.” ya da “büyük lokma ye büyük laf konuşma.”

Bol düşünmeli bir haftasonu dilerim 🙂

Bu yazı toplam 478 defa görüntülenmiştir.