Java – Object Oriented Kavramı III

Bu yazıda tamamen interface mantığı üzerinde durmak istiyorum. Çünkü önemli bir konu. Serinin ilk yazısında interface kavramına kısa bir giriş yapmıştık. Class‘ların dış dünya ile arayüzlerinin interface yardımıyla tanımlandığını ifade etmiştik. Ama tamamen yabancı birinin gözüyle bakmaya çalıştığımda bu tanım çok havada duruyor. Tanımı biraz daha açıp “class‘ta bulunması gereken methodların listesi” dediğimizde ise yine aynı gözler “iyi de neden böyle bişeye ihtiyaç duyuyoruz ki?, açar class‘ı bakarım” diye düşünebilirler. Çünkü genelde lisans eğitimi boyunca tek başınıza proje geliştirirsiniz. Bu durumda her modül elinizin altındadır. Ama hayat her zaman böyle olmayacaktır…

Büyük ve kurumsal bir firmada çalışıyor olabilirsiniz. Muhtemelen projelerde onlarca yazılımcı çalışacaktır ve bu yazılımcılar ayrı ayrı takımlara ayrılacaktır. Bu takımların her biri yazılımın bir bölümünü, bir modülünü geliştirecektir. Ve bu modüller mutlaka birbirleriyle ilişki içerisinde olacaktır. Bu noktada farklı gruplardaki yazılımcıların kendi geliştirdikleri modüllerin hangi noktalarda ne şekilde bir bağlantı kuracağı konusunda hemfikir olması gerekir. Her grubun kendi kodunu yazarken birde diğer grubun yazdıklarını takip etmesi büyük sıkıntı olur. Yazılımcı diğer grubun ne yaptığıyla ilgilenmeden kendi koduna odaklanmalıdır. Temasa geçilecek noktalarda ise iki tarafta belli bir kontrata uyacağını garanti etmelidir. “Kendi aramızda konuşup hallederiz” diyebilirsiniz, ama bu tabiki hiç pratik değil. Ayrıca böyle bir anlaşmadan compiler’ında haberi olmaz 🙂 İşte böyle noktalarda interface kullanmak hayati önem taşır.

Yukarıdaki senaryo biraz abartılı gelmiş olabilir fakat emin olun böyle durumlarla sık sık karşılaşacaksınız. Bunun için ayrı iki grup olmasına da gerek yok. Kendi yazdığınız iki modül de olabilir. Bir modülün diğerine bağımlılığını mümkün olduğunca azaltmak istiyor olabilirsiniz. Yani bir modül diğerinin içinde olup bitenle ilgilenmeden arayüzü ile temasa geçerse, gerçekleşecek değişim istekleri çok daha kolay handle edilebilir.

Somut bir örnek ile devam etmekte fayda var. Biraz ileri gidelim ve insansız otomobilleri icat edelim. İnsanlar otomobillerine biniyorlar ve sadece gidecekleri yeri söylüyorlar ve otomobil gidiyor. Bu durumda otomobil üreticileri bir yazılım ile araçlarının hareket etme, durma, dönme, sinyal verme gibi özelliklerini (method) tanımlayacaklardır. Tabi birde GPS şirketi olacak, uydu ve wireless teknoloji yardımıyla trafikte araçları kontrol edecek. Araç üreticilerinin tanımladığı özellikleri bu şirket güzergah ve trafik durumuna göre çağırarak kullanacak. Tabiki birden fazla otomobil üreticisi var ve hiçbiri diğerinin yazılımının içeriğini bilmiyor, müdahale edemiyor.

Bu senaryoda GPS şirketi bir interface belirtip “ürettiği araçların GPS sistemi ile otomatik olarak kontrol edilmesini isteyen tüm araç üreticileri benim belirlediğim interface’i implement etsin” diyebilir. Aşağıdaki gibi bir interface yayınlanır;

public interface OperateCar {

     //* varsa değişkenler (sadece constant olanlar)

     int turn(Direction direction, double radius, double startSpeed, double endSpeed);

     int changeLanes(Direction direction, double startSpeed, double endSpeed);

     int signalTurn(Direction direction, boolean signalOn);

     int getRadarFront(double distanceToCar, double speedOfCar);

     int getRadarRear(double distanceToCar, double speedOfCar);

         .....

     //* varsa diğer methodlar...
}

Bu interface tanımlandıktan sonra her araç üreticisi kendi aracına göre bu interface‘i implement eder. Örneğin BMW‘ninki şöyle birşey olabilir;

public class OperateBMW implements OperateCar {

     //* the OperateCar interface'inde belirtilen methodların içerikleri

     int turn(Direction direction, double radius, double startSpeed, double endSpeed) {
          //* BMW için sola dönme kodu
          //* BMW için sağa dönme kodu
     }
          .....

     //* Diğer methodlar da implement edilmeli..
}

Bu methodların içeriği her firma için farklı olsa da GPS şirketi hangi methodu çağıracağını ve hangi değişkenleri göndereceğini biliyor. İçerik önemli değil, sistem çalışır…

Java Programlama Dilinde;

  • Interface‘ler referans tipi olarak tanımlanır. Aynen class’lar gibi.
  • Sadece constantları ve method imzalarını içerirler. Methodların içeriği tanımlanmaz.
  • Interface‘ler için instantiation ve initialization gibi işlemler yapılmaz. Bu yüzden constructor kullanılmaz.
  • Bir interface ancak bir class tarafından implement edilebilir veya başka bir interface tarafından extend edilebilirler.

Application Programming Interface (API):

Interface‘ler şirketler arasında endüstri standardı olarak kullanılabilirler (yukarıdaki örnekte olduğu gibi). Bunlara Application Programming Interface (API) denir.

Örneğin Photoshop programı bazı özelliklerini bir interface yardımıyla piyasaya duyurur. Daha sonra photoshop eklentisi geliştirmek isteyen firmalar photoshop’ın kodlarına erişemedikleri halde bu interface‘leri implement ederek uygulamalar geliştirirler ve bu uygulamalar rahatlıkla photoshop ile birlikte çalışabilir. Her iki firma da kendi kodunun gizliliğini korurken aynı zamanda birlikte tek program gibi çalışan ürünler de ortaya çıkarmış olurlar. Ayrıca her iki firma da kendi ürününü zamanla upgrade edebilir, interface-implemantation ilişkisi bozulmadığı sürece ayrı ayrı upgrade’ler birlikte çalışmayı etkilemeyecektir.

Multi-Inheritance:

Serinin önceki yazılarında Java dilinin multi inheritance özelliğini desteklemediğini söylemiştik. Interface özelliği sayesinde buna bir alternatif getirilmiştir. Interface‘ler class hiyerarşisinde bulunmasalarda dolaylı olarak bu özelliği sağlarlar. Şöyle ki;

  • Bir class sadece bir classı extend edebilirken birden fazla interface‘i implement edebilir.
  • Bir object‘in run-time‘da birden fazla tipi olabilir, ve her tip için tanımlanan bir değişken ile object‘e referans verilebilir. Bu tipler şunlardır;
    • Kendi class‘ının tipi,
    • Extend ettiği üst class’ın tipi,
    • Implement ettiği tüm interface’lerin tipi.
  • Bir interface türünde değişken oluşturduğunuzda bu değişken bir pointer olur ve bu interface‘i implement eden class‘lardan herhangi birinin objectlerinden herhangi birine referans edebilir.

Bu maddeleri yukarıdaki örneği de kullanarak somutlaştırabiliriz;

//* Aynı interface'i implement eden class'lardan 3 farklı araba üretelim.
OperateBMW car1 = new OperateBMW();
OperateFord car2 = new OperateFord();
OperateMercedes car3 = new OperateMercedes();

//* interface türündeki bir değişken 3 arabaya da referans edebilir.
OperateCar opCar;
opCar = car1;
opCar = car2;
opCar = car3;

Bu özelliği bir sonraki yazıda anlatmayı düşündüğüm polymorphism başlığında kullanacağım. Önemlidir. Duyrulur 🙂

Özet:

Interface ile ilgili bildiklerimizi kısa kısa özetlersek;

  • Interface iki object arasındaki iletişim protokolüdür.
  • Interface tanımında sadece method imzaları ve constant değişkenler bulunabilir.
  • Inteface implement eden bir class, o interface‘deki methodların içeriğini tanımlamak zorundadır.
  • Interface, class‘ın aksine birden fazla interface‘i extend edebilir, fakat implement edemez.
  • Interface ismi referans tipi olarak kullanılabilir.

Interface kavramı önemli olduğu için bu kadar uzattım. Kullanılmadan önemi anlaşılmıyor. İnşallah yararlı bir yazı olmuştur. Sürç-ü lisan ettiysek affola 🙂

~ Şarkı ~