Java - Interface - 1

Java - Interface - 1

Arkadaşlar Merhaba,

Java dersleri serimize java'da interface kullanımı ile devam ediyoruz.

Java'da Interface Kullanımı

Java, birden çok durum mirasına (multiple inheritance of state) izin vermese de, bir sınıfın herhangi bir sayıda interface uygulamasına izin verir.

Bir interface, interface'i implement eden herhangi bir sınıfın sağlaması gereken soyut methodların bir listesini bildiren soyut bir veri tipidir diyebiliriz.

Bir interface ayrıca sabit değişkenler(constant variable) içerebilir. Bir interface'ye dahil edilen hem soyut methodlar hem de sabit değişkenler, dolaylı olarak public kabul edilir.

Dolayısıyla interfaceler sayesinde hiç bir gerçekleştirme bağımlılığı olmayan, tamamen interfaceye bağımlı yapılar oluşturulabilir.

Bu da düşük bağımlılık (low-coupling) ya da gevşek bağımlık (loose-coupling) demektir.

Java 8 ile interfaceler, statik ve default methodları içerecek şekilde güncellendi.

Default bir method interface methodunun bir gövdesine sahip olduğu ve soyut olarak işaretlenmediği bir methoddur.Geriye dönük uyumluluk için eklenmiştir ve eski bir sınıfın, mevcut sınıfı değiştirmek zorunda kalmadan yeni bir method içeren bir interfacenin yeni sürümünü kullanmasına olanak tanır.

Java 9'da, private ve private statik methodları desteklemek için interface'ler güncellendi. Bu türlerin her ikisi de bir interface bildiriminde kodun yeniden kullanılabilirliği için eklenmiştir ve interface tanımının dışında çağrılamaz.

  • Interface'lerin abstract olduğu varsayılır.

  • Interface değişkenlerinin public, statik ve final olduğu varsayılır.

  • Bir gövdesi olmayan interface methodların abstract ve public olduğu varsayılır.

GEÇERLİ SÖZ DİZİMLERİ ;

class1 extends class2 
interface1 extends interface2, interface3
class1 implements interface2, interface3

Siz eklemesiniz de interface dosyalarına implict modifiers eklenir.

Aşağıdaki kullanımların ikisi de eşdeğerdir. Sarı renkli olanlar ise implict modifiers olarak eklenen belirteçlerdir.

public interface Soar {
       int MAX_HEIGHT = 10;  
       final static boolean UNDERWATER = true;
       void fly(int speed);
       abstract void takeoff();
       public abstract double dive();
}

public abstract interface Soar {}

**public static final **int MAX_HEIGHT = 10;

public final static boolean UNDERWATER = true;

public abstract void fly(int speed);

public abstract void takeoff();

public abstract double dive();}

Conflict Modifiers

İnterfacelerdeki private ve protected erişim değiştiricileri ile ilgili sorunları tespit etmek kolay olsa da, package-private erişim ne olacak?

Örneğin, aşağıdaki iki öğe olan volume ve start() öğesinin erişim düzeyi public'dir.

public interface Sing {

    float volume = 10;

    abstract void start();

}

Sınıf üyeleriyle çalışırken, erişim değiştiricisinin belirtilmemesi,** varsayılan (paket-private) **erişimi gösterir.

**Interface **üyeleriyle çalışırken, erişim değiştiricisinin olmaması her zaman public erişimi gösterir.

Bir geliştirici, örtük bir (implicit modifier) değiştiriciyle çakışan bir değiştiriciyle bir methodu veya variable'ı işaretlerse ne olur?

Örneğin,soyut bir methodun public olduğu varsayılırsa, o zaman açıkça protected veya private olarak işaretlenebilir mi?

public interface Dance {
    private int count = 4; // DOES NOT COMPILE
    protected void step(); // DOES NOT COMPILE
}

Derleyici ortak değiştiriciyi her ikisine de uygulayacağından, bu interface üyesi bildirimlerinin hiçbiri derlenmedi ve bir çakışmayla sonuçlanacak.

private final interface Crawl{

    String distance;
    private int MAXIMUM_DEPTH = 100;
    protected abstract boolean UNDERWATER = false;
    private void dig(int depth);
    protected abstract double depth();
    public final void surface();
}

Interface tanımı olan ilk satır iki nedenden dolayı derlenmeyecektir.

Interface final olarak işaretlendiğinden implict modifiers abstract ile çakışacaktır.Diğer bir neden ise private olarak işaretlendiğinden dolayı public ve package-private ile çakışacaktır.

**String distance **alanı ise Interface değişkenlerinin statik final sabitler olarak varsayıldığını ve bildirildiğinde başlatıldığı için burada derleyici hata verecektir çünkü distance değişkeni başlatılmamış.

MAXIMUM_DEPTH ise interface değişkenlerinin public olduğu varsayıldığı için private olarak tanımlanarak bu tanımlama ile çakışır ve satır derlenmez.

UNDERWATER ise interface değişkenlerinin public olduğu varsayıldığı için protected olarak tanımlanarak bu tanımlama ile çakışır ve satır derlenmez.

dig methodu tüm interface soyut methodların public olduğu varsayıldığından ve private veya protected olarak işaretlenmesine izin verilmediğinden, bu satırda derlenmez.

**depth methodu ** tüm interface soyut methodların public olduğu varsayıldığından ve private veya protected olarak işaretlenmesine izin verilmediğinden, bu satırda derlenmez.

surface methodu final olarak işaretlendiğinden ve gövdesi olmayan interface methodlarının abstract olduğu varsayıldığından,derleyici bir methodda hem soyut hem de final anahtar sözcükleri kullanmak için bir istisna atar.

public interface Animal {

    String name();
}

public interface BigCat {

    String type();
}

public class Lion implements Animal , BigCat{

    @Override
    public String name() {
        return "Aslan";
    }

    @Override
    public String type() {
        return "Panthera";
    }
}

Bu örnekte Lion sınıfı iki interfacesi birden uygulamaktadır.

Interfaceler bir sınıf hiyerarşisinin parçası olarak başlatılmadığından iki interfacenin genişletilmesine izin verilir.

Soyut sınıflardan farklı olarak constructors içermezler ve instance initialization bir parçası değildirler.

Interfaceler basitçe, onları uygulayan bir sınıfın uyması gereken bir dizi kuralı tanımlar.

Ayrıca, sınıfın bir instancesinin kullanılmasını gerektirmeyen sabitler(constant) de dahil olmak üzere çeşitli statik üyeler içerirler.

Ayrıca bir Java dosyasının en fazla bir public üst düzey sınıfı veya interface'i olabilir ve dosyanın adıyla eşleşmesi gerekir.

**Bir üst düzey sınıf veya inteface yalnızca public veya package-private erişimiyle bildirilebilir. **

Abstract Sınıf vs Interface

public interface Leagues {

    Date start();
}

abstract class SoccerLeague {

    Date start() {
        return null;
    }
}

Soyut sınıflar ve arabirimlerin her ikisi de soyut türler olarak kabul edilse de, yalnızca interfaceler örtük değiştiricileri(implict modifiers) kullanır.

Bu, benzer bildirimlere sahip bir abstract sınıf ve interface'nin çok farklı özelliklere sahip olabileceği anlamına gelir.

Örneğin start() methodlarının her ikisi de soyut olarak kabul edilir.Bununla birlikte** start() abstract olarak işaretlenmez ise SoccerLeague sınıfı derlenmeyecektir.**

Leagues interfacesi ise abstract olarak işaretlense de işaretlenmese de derlenecektir.

**Ayrıca her iki start() methodu da erişim belirteci olmamasına rağmen aynı erişim düzeyine sahip değillerdir. **

abstract SoccerLeague sınıfında ki varsayılan olarak(package-private) olarak kabul edilirken, interface Leagues sınıfı public olarak değerlendirilir.

public class WomenSoccerLeague implements Leagues{

   Date start() {
         return null;
     }
}

İki method uygulaması aynı olsa da, WomenSoccerLeague sınıfındaki method, method override etme kurallarını çiğner. Leagues arabiriminden, devralınan soyut methodun public olduğu varsayılır ve WomenSoccerLeague sınıfındaki start() tanımı bu nedenle görünürlüğü azaltır.

Bir methodun public'den package-private dönüştürülmesi, derleyici hatasına neden olur. WomenSoccerLeague sınıfının doğru uygulaması aşağıdadır:

@Override
public Date start() { }

Interface ve Miras Almak

Bir interface üç yoldan biriyle miras alınabilir.

  • Bir interface, başka bir interface'i extend edebilir.

  • Bir sınıf bir interface'i implement edebilir.

  • Bir sınıf, ataları bir interface uygulayan başka bir sınıfı genişletebilir.

Bir interface miras alındığında, tüm soyut methodlar miras alınır. Soyut sınıflarda gördüğümüz gibi,interface'yi devralan tür de bir interface veya abstract sınıf gibi soyut ise, interface methodlarını uygulamak gerekli değildir.

Öte yandan, interface'yi devralan ilk somut alt sınıf, devralınan tüm soyut methodları uygulamak zorundadır.

public interface MenLeagues {

    String leagueName();
}

public interface WomenLeagues {

    String womenLeagueName();
}

public abstract class Leagues implements MenLeagues , WomenLeagues{}

Leagues sınıfı, abstract olarak işaretlendiğinden, MenLeagues ve WomenLeagues devraldığı metotlardan herhangi birini implement etmek zorunda değildir.

public class EuropeanLeagues extends Leagues{

   protected Date start(){
        return null;
    }

    @Override
    public String leagueName() {
        return null;
    }

    @Override
    public String womenLeagueName() {
        return null;
    }
}

İlk somut sınıf olan EuropeanLeagues ise tüm methodları ise devralmak zorundadır.

Tekrar bir somut sınıf EuropeanLeagues sınıfını kalıtıyoruz.İkinci somut sınıfımız olan bu sınıfta ise yine tüm methodları uygulamak zorunda değiliz.

public class TurkishLeague extends EuropeanLeagues{}