CodeGym /Java Blogu /Rastgele /Neden Java'da Arayüzlere İhtiyacımız Var?
John Squirrels
Seviye
San Francisco

Neden Java'da Arayüzlere İhtiyacımız Var?

grupta yayınlandı
MERHABA! Bugün Java'daki önemli bir kavramdan bahsedeceğiz: arayüzler. Kelime muhtemelen size tanıdık geliyor. Örneğin, çoğu bilgisayar programının ve oyunun arayüzü vardır. Geniş anlamda, bir arayüz etkileşim halindeki iki tarafı birbirine bağlayan bir tür 'uzaktan kumanda'dır. Günlük yaşamdaki basit bir arayüz örneği, bir TV uzaktan kumandasıdır. Bir kişi ve bir TV olmak üzere iki nesneyi birbirine bağlar ve farklı görevleri yerine getirir: sesi açın veya kapatın, kanal değiştirin ve TV'yi açın veya kapatın. Bir tarafın (kişi), ikinci tarafın eylemi gerçekleştirmesini sağlamak için arayüze erişmesi (uzaktan kumandadaki bir düğmeye basması) gerekir. Örneğin, TV'nin bir sonraki kanala geçmesini sağlamak için. Dahası, kullanıcı TV'nin nasıl düzenlendiğini veya kanal değiştirme sürecinin dahili olarak nasıl uygulandığını bilmeye gerek yoktur. Kullanıcının erişebildiği tek şey arayüzdür. İstenilen sonucu elde etmek temel amaçtır. Bunun programlama ve Java ile ne ilgisi var? Her şey :) Bir arayüz oluşturmak, normal bir sınıf oluşturmaya çok benzer, ancak bunun yerine kelimeyi kullanmaksınıf , arayüz kelimesini belirtiyoruz . En basit Java arayüzüne bakalım, nasıl çalıştığını ve neden ihtiyacımız olduğunu görelim:

public interface CanSwim {

     public void swim();
}
Bir CanSwim arayüzü oluşturduk . Bu biraz bizim uzaktan kumandamız gibi, ama bir 'düğme' ile: swim() yöntemi. Peki bu uzaktan kumandayı nasıl kullanacağız? Bunun için bir method yani uzaktan kumanda butonumuzu uygulamamız gerekiyor. Bir arabirimi kullanmak için, programımızdaki bazı sınıfların onun yöntemlerini uygulaması gerekir. Nesneleri 'yüzebilen' bir sınıf icat edelim. Örneğin, bir Duck sınıfı şunlara uyar:

public class Duck implements CanSwim {

    public void swim() {
        System.out.println("Duck, swim!");
    }

    public static void main(String[] args) {

        Duck duck = new Duck();
        duck.swim();
    }
}
"Burada ne görüyoruz? Duck sınıfı, implements anahtar kelimesiyle CanSwim arabirimiyle 'ilişkilendirilir' . İki sınıfı kalıtım yoluyla ilişkilendirmek için benzer bir mekanizma kullandığımızı hatırlayabilirsiniz, ancak bu durumda "extens" kelimesini kullandık. tam bir açıklık, ' public class Duck implements CanSwim ' ifadesini kelimenin tam anlamıyla şu şekilde çevirebiliriz : 'The public Duck class implements the CanSwim interface'. Bu, bir arabirimle ilişkilendirilmiş bir sınıfın tüm yöntemlerini uygulaması gerektiği anlamına gelir. Not: sınıfımız , tıpkı arayüzün bir metodu var ve biraz da mantık içeriyor bu zorunlu bir gereklilik sadece yazacak olursakDuckCanSwimswim()public class Duck implements CanSwimswim()sınıfta bir yöntem oluşturmadan Duck, derleyici bize bir hata verecektir: Duck soyut değildir ve CanSwim'deki yüzme() soyut yöntemini geçersiz kılmaz Neden? Bu neden oluyor? Hatayı TV örneği üzerinden açıklayacak olursak, birine kanal değiştiremeyen 'kanal değiştir' düğmesi olan bir TV kumandası vermek gibi olur. Düğmeye istediğiniz kadar basabilirsiniz, ancak çalışmaz. Uzaktan kumanda kanalları kendi başına değiştirmez: TV'ye yalnızca karmaşık kanal değiştirme sürecini uygulayan bir sinyal gönderir. Ve ördeğimizde de durum böyle: Arayüz kullanılarak çağrılabilmesi için nasıl yüzüleceğini bilmesi gerekir CanSwim. Nasıl olduğunu bilmiyorsa,CanSwimarayüz iki tarafı - kişi ve programı - bağlamaz. Kişi program içerisinde yüzme swim()yapmak için yöntemi kullanamayacaktır . DuckArtık arayüzlerin ne işe yaradığını daha net anlıyorsunuz. Arayüz, arayüzü uygulayan sınıfların sahip olması gereken davranışı tanımlar. 'Davranış' bir yöntemler topluluğudur. Birkaç haberci oluşturmak istiyorsak, yapılacak en kolay şey bir Messengerarayüz oluşturmaktır. Her habercinin neye ihtiyacı vardır? Temel düzeyde, mesaj alıp gönderebilmeleri gerekir.

public interface Messenger{

     public void sendMessage();

     public void getMessage();
}
Artık ilgili arayüzü uygulayan haberci sınıflarımızı kolayca oluşturabiliriz. Derleyicinin kendisi bizi bunları sınıflarımızda uygulamaya 'zorlayacaktır'. Telgraf:

public class Telegram implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a Telegram message!");
    }

     public void getMessage() {
         System.out.println("Receiving a Telegram message!");
     }
}
Naber:

public class WhatsApp implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a WhatsApp message!");
    }

     public void getMessage() {
         System.out.println("Reading a WhatsApp message!");
     }
}
Viber:

public class Viber implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a Viber message!");
    }

     public void getMessage() {
         System.out.println("Receiving a Viber message!");
     }
}
Bu ne gibi avantajlar sağlıyor? Bunlardan en önemlisi gevşek bağlantıdır. İstemci verilerini toplayacak bir program tasarladığımızı hayal edin. Sınıfın, Clientmüşterinin hangi özel haberciyi kullandığını belirtmek için kesinlikle bir alana ihtiyacı vardır. Arayüzler olmadan, bu garip görünürdü:

public class Client {

    private WhatsApp whatsApp;
    private Telegram telegram;
    private Viber viber;
}
Üç alan oluşturduk, ancak bir müşteri yalnızca bir haberciye sahip olabilir. Sadece hangisi olduğunu bilmiyoruz. Bu nedenle, müşteri ile iletişim kurabilmek için sınıfa her olasılığı eklemeliyiz. Görünüşe göre bunlardan bir veya ikisi her zaman null, program tarafından tamamen gereksiz olacak. Bunun yerine arayüzümüzü kullanmak daha iyidir:

public class Client {

    private Messenger messenger;
}
Bu bir gevşek bağlantı örneğidir! Sınıfta belirli bir haberci sınıfı belirtmek yerine Client, sadece istemcinin bir habercisi olduğunu belirtiriz. Program çalışırken tam olarak hangisi belirlenecektir. Peki bunun için neden arayüzlere ihtiyacımız var? Neden dile eklendiler? Bu iyi bir soru - ve doğru soru! Sıradan kalıtımı kullanarak aynı sonucu elde edemez miyiz? MessengerEbeveyn olarak sınıf ve çocuklar olarak , Viber, Telegramve . WhatsAppGerçekten de bu mümkün. Ama bir pürüz var. Bildiğiniz gibi, Java'nın çoklu kalıtımı yoktur. Ancak çoklu arayüz desteği var. Bir sınıf, istediğiniz kadar arayüz uygulayabilir. SmartphoneBir tane olan bir sınıfımız olduğunu hayal edin.Appakıllı telefona yüklenmiş bir uygulamayı temsil eden alan.

public class Smartphone {

    private App app;
}
Elbette, bir uygulama ve bir haberci benzerdir, ancak yine de farklı şeylerdir. Bir habercinin mobil ve masaüstü sürümleri olabilir, ancak Uygulama özellikle bir mobil uygulamayı temsil eder. Telegramİşte anlaşma - kalıtımı kullansaydık, sınıfa bir nesne ekleyemezdik Smartphone. Sonuçta, Telegramsınıf aynı anda Appve Messenger! Ve onu zaten miras aldık Messengerve sınıfa ekledik Client. Ancak Telegramsınıf, her iki arabirimi de kolayca uygulayabilir! ClientBuna göre sınıfa bir Telegramnesneyi a olarak verebiliriz ve onu da sınıfa bir olarak Messengerverebiliriz . Bunu şu şekilde yapabilirsiniz: SmartphoneApp

public class Telegram implements Application, Messenger {

    // ...methods
}

public class Client {

    private Messenger messenger;

    public Client() {
        this.messenger = new Telegram();
    }
}


public class Smartphone {

    private Application application;

    public Smartphone() {
        this.application = new Telegram();
    }
}
TelegramŞimdi sınıfı istediğimiz gibi kullanıyoruz . Bazı yerlerde, bir App. Diğer yerlerde, bir Messenger. Arayüz yöntemlerinin her zaman 'boş' olduğunu, yani uygulamalarının olmadığını zaten fark etmişsinizdir. Bunun nedeni basittir: Arayüz davranışı tanımlar, ancak onu uygulamaz. "Ara yüzü uygulayan tüm nesneler CanSwimyüzebilmelidir": arabirimin bize söylediği tek şey bu. Balıkların, ördeklerin ve atların yüzme şekli Fish, Duck, veHorsesınıflar, arayüz değil. Tıpkı kanal değiştirmenin TV için bir görev olduğu gibi. Uzaktan kumanda bunun için size bir düğme verir. Bununla birlikte, Java 8'de ilginç bir ekleme ortaya çıktı - varsayılan yöntemler. Örneğin, arabiriminizin 10 yöntemi vardır. 9 tanesinin farklı sınıflarda farklı uygulamaları var, ancak biri hepsi için aynı şekilde uygulanıyor. Önceden, Java 8'den önce, arabirim yöntemlerinin hiçbir uygulaması yoktu: derleyici hemen bir hata verdi. Şimdi böyle bir şey yapabilirsiniz:

public interface CanSwim {

   public default void swim() {
       System.out.println("Swim!");
   }

   public void eat();

   public void run();
}
Anahtar kelimeyi kullanarak default, varsayılan uygulama ile bir arayüz yöntemi oluşturduk. eat()Diğer iki yöntem için - ve run()- uygulayan tüm sınıflarda kendi uygulamamızı sağlamamız gerekir CanSwim. Bunu metotla yapmamıza gerek yok swim(): uygulama her sınıfta aynı olacak. Bu arada, fark etmemiş olsanız bile geçmiş görevlerde arayüzlerle zaten karşılaştınız :) İşte canlı bir örnek: ve arayüzleri Java'da arabirimler neden gereklidir - 2ile çalıştınız ! Daha kesin olarak, onların uygulamalarıyla çalıştınız — , , , vs. Örneğin, uygular veListSetArrayListLinkedListHashSetLinkedListListDeque(çift uçlu kuyruk) arabirimleri. MapArayüze, daha doğrusu uygulamasına aşinasınız HashMap. Bu arada, bu diyagram bir özelliği göstermektedir: arayüzler diğer arayüzleri miras alabilir. Arabirim miras alırken SortedMapmiras alır . Bir arabirimin diğerinin genişletilmiş sürümü olduğu arabirimler arasındaki ilişkiyi göstermek istiyorsanız bu gereklidir. Arayüz ile bir örnek ele alalım . Henüz incelemedikMapDequeQueueQueueQueues, ancak oldukça basittir ve bir mağazadaki sıradan bir sıra veya sıra gibi çalışır. Öğeleri yalnızca kuyruğun sonuna ekleyebilir ve yalnızca baştan alabilirsiniz. Bir noktada geliştiriciler, her iki uca da öğe eklemek ve almak için kuyruğun gelişmiş bir sürümüne ihtiyaç duydu. DequeBöylece çift uçlu bir sıra olan bir arayüz oluşturdular . Sıradan bir kuyruğun tüm yöntemlerine sahiptir. Ne de olsa, çift uçlu kuyruğun ebeveyni ama aynı zamanda yeni yöntemler de ekliyor.
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION