izmir escort escort izmir porno porno izle
Java - Arayüzler (Interface) - IRCForumları - IRC ve mIRC Yardım ve Destek Platformu
User Tag List

Arrow Java - Arayüzler (Interface) #1
Üyelik Tarihi: 10 Eylül 2012
Mesajlar: 3.858
Aldığı Beğeni: 1
Beğendikleri: 0
23 Ekim 2012 , 18:34
Alıntı ile Cevapla
Kategorisi : J# ve Java dili

Diğer programlama dillerinde olan çoklu kalıtım (multiple inheritance) özelliği Java programlama dilinde yoktur. Java programlama dilinde çoklu kalıtım desteğinden faydalanmak için arayüz (interface) ve dahili sınıflar (inner classes) kullanılır.

Bu makalemizde ise Bu iki destekten interface arayüz kavramını incelemeye çalışacağız.

Arayüz (Interface)

Arayüzler, soyut (abstract) sınıfların bir üst modeli gibi düşünülebilir, soyut sınıfların içerisinde hem iş yapan hem de hiçbir iş yapmayan sadece birleştirici rol üstlenen gövdesiz yordamlar (soyut yordamlar-abstract methods) vardı. Bu birleştirici rol oynayan yordamlar, soyut sınıftan (abstract class) türetilmiş alt sınıfların içerisinde iptal edilmeleri (override) gerektiğini polimorfizim makalemizde incelenmişti. Arayüzlerin içerisinde ise iş yapan herhangi bir yordam (method) bulunamaz; arayüzün içerisinde tamamen gövdesiz yordamlar (soyut yordamlar) bulunur. Bu açıdan bakılacak olursak, arayüzler, birleştirici bir rol oynamaları için tasarlanmıştır. Önemli bir noktayı hemen belirtelim; ara yüzlere ait gövdesiz (soyut) yordamlar otomatik olarak public erişim belirleyicisine sahip olurlar ve sizin bunu değiştirme imkânınız yoktur. Aynı şekilde arayüzlere ait global alanlarda otomatik public erişim belirleyicisine sahip olurlar ek olarak, bu alanlar yine otomatik olarak final ve statik özelliği içerirler ve sizin bunlara yine müdahale etme imkanınız yoktur.

Birleştiricilik

Bir önceki Java makalemiz olan Polimorfizm yazımızda verilen BüyükIsYeri örneğini, arayüzleri kullanarak baştan yazmadan önce, yeni UML diyagramını inceleyelim;



UML diyagramında görüldüğü üzere, Calisan arayüzü (interface), birleştirici bir rol oynamaktadır. Calisan arayüzünde tanımlanan ve soyut (gövdesiz) calis() yordamı (method), bu arayüze erişen tüm sınıfların içerisinde iptal edilmek zorundadır (override). UML diyagramımızı Java uygulamasına dönüştürülürse;

BuyukIsYeri.java
interface Calisan { // arayuz
public **** calis() ;
}

class mudur implements Calisan {
public **** calis() { // iptal etti (override)
System.out.println("Mudur Calisiyor");
}
}

class genelMudur extends Mudur {
public **** calis() { // iptal etti (override)
System.out.println("GenelMudur Calisiyor");
}
public **** toplantiYonet() {
System.out.println("GenelMudur toplanti yonetiyor");
}
}

class programci implements Calisan {
public **** calis() { // iptal etti (override)
System.out.println("Programci Calisiyor");
}
}

class AnalizProgramci extends Programci {
public **** analizYap() {
System.out.println("Analiz Yapiliyor");
}
}

class SistemProgramci extends Programci {
public **** sistemIncele() {
System.out.println("Sistem Inceleniyor");
}
}

class Pazarlamaci implements Calisan {
public **** calis() { // iptal etti (override)
System.out.println("Pazarlamaci Calisiyor");
}
}

class Sekreter implements Calisan {
public **** calis() { // iptal etti (override)
System.out.println("Sekreter Calisiyor");
}
}

public class BuyukIsYeri {
public static **** mesaiBasla(Calisan[] c ) {
for (int i = 0 ; i < c.length ; i++) {
c[i].calis(); // ! Dikkat !
}
}

public static **** main(String args[]) {
Calisan[] c = new Calisan[6];
// c[0]=new Calisan(); ! Hata ! arayüz olusturulamaz
c[0]=new Programci(); // yukari cevirim (upcasting)
c[1]=new Pazarlamaci(); //yukari cevirim (upcasting)
c[2]=new Mudur(); //yukari cevirim (upcasting)
c[3]=new GenelMudur(); //yukari cevirim (upcasting)
c[4]=new AnalizProgramci(); //yukari cevirim (upcasting)
c[5]=new SistemProgramci(); //yukari cevirim (upcasting)
mesaiBasla(c);
}
}
Yukarıdaki örneğimiz ilk etapta çekici gelmeyebilir, �Bunun aynısı soyut sınıflarla (abstract class) zaten yapılabiliyordu. Arayüzleri neden kullanayım ki... � diyebilirsiniz. Yukarıdaki örnekte arayüzlerin nasıl kullanıldığı incelenmiştir; arayüzlerin sağladığı tüm faydalar birazdan daha detaylı bir şekilde incelenecektir.

Arayüzlerin devreye sokulmasını biraz daha yakından bakılırsa.

class Mudur implements Calisan {
public **** calis() { // iptal etti (override)
System.out.println("Mudur Calisiyor");
}
}
Olaylara Mudur sınıfının bakış açısından bakılsın. Bu sınıf Calisan arayüzünün gövdesiz yordamlarını iptal etmek (override) istiyorsa, Calisan arayüzüne ulaşması gerekir. Bu ulaşım implements anahtar kelimesi ile gerçekleşir. Mudur sınıfı bir kere Calisan arayüzüne ulaştımı, buradaki gövdesiz yordamları (soyut yordamları) kesin olarak iptal etmek (override) zorundadır. Uygulamanın çıktısı aşağıdaki gibidir;

Programci Calisiyor
Pazarlamaci Calisiyor
Mudur Calisiyor
GenelMudur Calisiyor
Programci Calisiyor
Programci Calisiyor

Arayüz (Interface) ve Soyut Sınıflar (Abstract Classes)

Eğer bir sınıf (soyut sınıflar dâhil) bir arayüze (interface) ulaşmak istiyorsa, bunu implements anahtar kelimesi ile gerçekleştirebileceğini belirtmiştik. Ayrıca eğer bir sınıf bir kere arayüze ulaşımı artık onun tüm gövdesiz yordamlarını (soyut yordamlar) kesin olarak iptal etmesi (override) gerektiğini de belirttik. Peki, eğer soyut bir sınıf (abstract class) bir arayüze ulaşırsa, arayüze ait gövdesiz yordamları kesin olarak, kendi içerisinde iptal etmeli mi? Bir örnek üzerinde incelersek;

hayvanat.java
interface Hayvan {
public **** avlan() ;
}

abstract class Kedi implements Hayvan {
}
Yukarıdaki örneğimizi derleyebilir (compile) miyiz? Derlense bile çalışma anında (run-time) hata oluşturur mu? Aslında olaylara kavramsal olarak bakıldığında çözüm yakalanmış olur. Soyut sınıfların amaçlarından biri aynı arayüz özelliğinde olduğu gibi birleştirici bir rol oynamaktır. Daha açık bir ifade kullanırsak, hem arayüzler olsun hem de soyut sınıflar olsun, bunların amaçları kendilerine ulaşan normal sınıflara, kendilerine ait olan gövdesiz yordamları iptal ettirmektir (override). O zaman yukarıdaki örnekte soyut olan Kedi sınıfı, Hayvan arayüzüne (interface) ait gövdesiz (soyut) avlan() yordamını iptal etmek zorunda değildir. Daha iyi anlaşılması açısından yukarıdaki örneği biraz daha geliştirelim ama öncesinde UML diyagramını çıkartalım;



UML diyagramından görüleceği üzere, Kaplan sınıfı, avlan() ve takipEt() yordamlarını (gövdesiz-soyut yordamlarını) iptal etmek zorundadır. UML diyagramını Java uygulamasına dönüştürülürse;

hayvanat2.java
interface Hayvan {
public **** avlan() ;
}

abstract class Kedi implements Hayvan {
public abstract **** takipEt() ;
}

class Kaplan extends Kedi {
public **** avlan() { // iptal etti (override)
System.out.println("Kaplan avlaniyor...");
}

public **** takipEt() { // iptal etti (override)
System.out.println("Kaplan takip ediyor...");
}
}
Soyut (abstract) olan Kedi sınıfının içerisinde, herhangi bir gövdesiz yordam (soyut yordam) iptal edilmemiştir (override). İptal edilme işlemlerinin gerçekleştiği tek yer Kaplan sınıfının içerisidir. Soru: Kaplan sınıfı Hayvan arayüzünde (interface) tanımlanmış soyut olan (gövdesiz) avlan() yordamını iptal etmek (override) zorunda mı? Cevap: Evet, çünkü Kaplan sınıfı Kedi sınıfından türetilmiştir. Kedi sınıfı ise Hayvan arayüzüne ulaşmaktadır. Bu sebepten dolayı Kaplan sınıfının içerisinde avlan() yordamı iptal edilmelidir.

En baştaki sorumuzun cevabı olarak, hayvanat.java örneğimiz rahatlıkla derlenebilir (compile) ve çalışma anında (run-time) herhangi bir çalışma-anı istisnasına (runtime-exception) sebebiyet vermez. (Not: İstisnaları (Exception) bir sonraki makalemizde detaylı bir biçimde incelemeye çalışacağız.)

Arayüz (Interface) İle Çoklu Kalıtım (Multiple Inheritance)

İlk önce çoklu kalıtımın (multiple inheritance) niye tehlikeli ve Java programlama dili tarafından kabul görmediğini inceleyelim. Örneğin Programci soyut sınıfından türetilmiş iki adet sınıfımız bulunsun, Yazilimci ve Analist sınıfları. Bu iki sınıftan türetilen yeni bir sınıf olamaz mı? Örneğin CoderTurhal sınıfı; yani, CoderTurhal sınıfı aynı anda hem Yazilimci, hem de Analist sınıfından türetilebilir mi? Java programlama dilinde türetilemez. Bunun sebeplerini incelemeden evvel, hatalı yaklaşımı UML diyagramında ifade edilirse;



Java programlama dili niye çoklu kalıtımı bu şekilde desteklemez? UML diyagramını, hatalı bir Java uygulamasına dönüştürülürse;

Program.java
abstract class Programci {
public abstract **** calis();
}

class Yazilimci extends Programci {
public **** calis() {
System.out.println("Yazilimci calisiyor....") ;
}
}

class Analist extends Programci {
public **** calis() {
System.out.println("Analist calisiyor....") ;
}
}

/*
Bu ornegimiz derleme aninda hata alicaktir.
Java, coklu kalitimi desteklemez
*/
class CoderTurhal extends Yazilimci, Analist {
}
Program.java derleme anında hata alacaktır. Bu ufak ayrıntıyı belirttikten sonra, kaldığımız yerden devam edelim. Java�nın niye çoklu kalıtımı (multiple inheritance) desteklemediğini anlamak için aşağıdaki gösterim incelenmelidir.

Programci s = new CoderTurhal(); // yukari dogru cevirim
s.calis(); // ??
Herhangi bir yerden, yukarıdaki gösterimde belirtildiği gibi bir ifade yazılmış olsa, sonuç nasıl olurdu? Programci tipinde olan referans, CoderTurhal nesnesine bağlanmıştır (bağlanabilir çünkü arada kalıtım ilişkisi vardır). Fakat burada s.calis() ifadesi yazılırsa, hangi nesnenin calis() yordamı çağrılacaktır? Yazilimci nesnesinin mi? Yoksa Analist nesnesinin mi? Sonuçta, calıs() yordamı, Yazilimci ve Analist sınıflarının içerisinde iptal edilmiştir. Bu sorunun cevabı yoktur. Fakat çoklu kalıtımın bu zararlarından arıtılmış versiyonunu yani arayüzleri (interface) ve dâhili sınıflar (inner classes) kullanarak, diğer dillerinde bulunan çoklu kalıtım desteğini, Java programlama dilinde de bulmak mümkündür. �Peki ama nasıl?� diyenler için hemen örneğimizi verelim. Yukarıdaki örneğimizi Java programlama diline uygun bir şekilde baştan yazalım ama öncesinde her zaman ki gibi işe UML diyagramını çizmekle başlayalım;




CoderTurhal, belki aynı anda hem Yazilimci hemde Analist olamaz ama onlara ait özelliklere sahip olabilir. Örneğin Yazilimci gibi buz üzerinde kayabilir ve Analist gibi şut atabilir. Yukarıdaki UML diyagramı Java uygulamasına dönüştürülürse.

Program2.java
interface ProgramYazabilme {
public **** programYaz();
}

interface AnalizYapabilme {
public **** analizYap();
}

class CoderTurhal implements ProgramYazabilme, AnalizYapabilme {
public **** programYaz() {
System.out.println("CoderTurhal program yaziyor");
}
public **** analizYap() {
System.out.println("CoderTurhal analiz yapıyor");
}
}
Bu örneğimizde CoderTurhal, ProgramYazabilme ve AnalizYapabilme özelliklerine sahip olmuştur. Arayüzler içerisindeki (ProgramYazabilme,AnalizYapabilme) gövdesiz (soyut) yordamları (programYaz(), analizYap()), bu arayüzlere erişen sınıf tarafından kesinlikle iptal edilmelidir (overrride). Eğer iptal edilmez ise, derleme anında (compile-time) Java tarafından gerekli hata mesajı verilir.

Örneğimizden anlaşılabileceği üzere arayüz (interface) ile soyut (abstract) sınıf arasında büyük fark vardır. En başta kavramsal olarak bir fark vardır. Bu kavramsal fark nedir derseniz hemen açıklayalım; Soyut bir sınıftan türetilme yapıldığı zaman, türetilen sınıf ile soyut sınıf arasında mantıksal bir ilişki olması gerekirdi, örnek vermek gerekirse "Yarasa bir Hayvandır" gibi veya "Müdür bir Çalışandır" gibi� Geçen bölümlerde incelediğimiz bir ilişkisi. Fakat arayüzler ile bunlara erişen sınıflar arasında kalıtımsal bir ilişki bulunmayabilir.

Arayüzlerin Kalıtım (İnheritance) Yoluyla Genişletilmesi

Bir arayüz başka bir arayüzden türetilerek yeni özelliklere sahip olabilir; böylece arayüzler kalıtım yoluyla genişletilmiş olur. Olayları daha iyi anlayabilmek için önce UML diyagramını çizip sonrada Java uygulamasını yazalım.



Avlanabilme arayüzü, DahaHizliKosabilme arayüzünden türemiştir. DahaHizliKosabilme arayüzüde Kosabilme arayüzünde türemiştir. Yukarıdaki UML diyagramımızı Java uygulamasına dönüştürelim;

Jaguar.java
interface Kosabilme {
public **** kos();
}

interface DahaHizliKosabilme extends Kosabilme {
public **** dahaHizliKos();
}

interface Avlanabilme extends DahaHizliKosabilme {
public **** avlan();
}

class RoadRunner implements DahaHizliKosabilme {
public **** kos() {
System.out.println("RoadRunner kosuyor, bip ");
}

public **** dahaHizliKos() {
System.out.println("RoadRunner kosuyor, bip bippp");
}
}

public class Jaguar implements Avlanabilme {
public **** avlan() {
System.out.println("Juguar avlaniyor");
}

public **** dahaHizliKos() {
System.out.println("Juguar daha hizli kos");
}

public **** kos() {
System.out.println("Juguar Kosuyor");
}
}
Jaguar sınıfı Avlanabilme arayüzüne ulaşarak, avlan(), dahaHizliKos(), kos() yordamlarını iptal etmek (override) zorunda bırakılmıştır. Bunun sebebi Avlanabilme arayüzünün DahaHizliKosabilme arayüzünden, DahaHizliKosabilme arayüzününde Kosabilme arayüzünden türemiş olmasıdır.

RoadRunner sınıfı ise sadece DahaHizliKosabilme arayüzüne erişerek, kos() ve dahaHizliKos() gövdesiz (soyut) yordamlarını iptal etmek (override) zorunda bırakılmıştır. Yine bunun sebebi DahaHizliKosabilme arayüzünün Kosabilme arayüzünden türemiş olmasıdır.

Arayüzlere Özel

Şimdi birazdan inceleyeceğiz olay sadece arayüzler söz konusu olduğunda yapılabilir. İlk olayımız açıklayalım; Bir arayüz (interface) birden çok arayüzden türetilebilir.

interface C {
//..
}

interface B {
//..
}

interface A extends B, C {
//..
}
Yukarıdaki gösterimde, A arayüzü, birbirlerinden bağımsız iki arayüzden türetilmiş oldu. İkinci olay ise daha evvelde incelenmişti (bkz:Program2.java) ama bir kere daha üzerine basa basa durmakta fayda var; bir sınıf birden fazla arayüze rahatlıkla erişebilir.

Çakışmalar

Arayüzlerin içerisinde dönüş tipleri haricinde her şeyleri aynı olan gövdesiz (soyut) yordamlar varsa, bu durum beklenmedik sorunlara yol açabilir. Yazılanları Java uygulaması üzerinde gösterilirse;

Cakisma.java
interface A1 {
public **** hesapla();
}

interface A2 {
public **** hesapla(int d);
}

interface A3 {
public int hesapla();
}

class S1 implements A1,A2 { // sorunsuz
public **** hesapla() { //adas yordamlar(overloaded)
System.out.println("S1.hesapla");
}
public **** hesapla(int d) { //adas yordamlar(overloaded)
System.out.println("S1.hesapla " + d );
}
}

/*
! Hatali !, adas yordamlar (overloaded)
donus tiplerine gore ayirt edilemez
*/

class S2 implements A1,A3 {
public **** hesapla() {
System.out.println("S2.hesapla");
}

/* ! Hata !
public int hesapla() {
System.out.println("S2.hesapla");
return 123;
}
*/
}
Cakisma.java örneğini derlenirse (compile), aşağıdaki hata mesajı ile karşılaşılır:

Cakisma.java:27: hesapla() in S2 cannot implement hesapla() in A3; attempting to
use incompatible return type
found : ****
required: int
class S2 implements A1,A3 {
^
1 error
Bu hatanın oluşma sebebi, A1 ve A3 arayüzlerinin içerisindeki gövdesiz (soyut) yordamlarından kaynaklanır. Bu yordamların isimleri ve parametreleri aynıdır ama dönüş tipleri farklıdır.

public **** hesapla(); // A1 arayüzüne ait
public int hesapla(); // A3 arayüzüne ait
İki yordamın adaş yordam (overloaded method) olabilmesi için bu yordamların parametrelerinde kesin bir farklılık olması gerekirdi. İki yordamın dönüş tipleri dışında her şeyleri aynıysa bunlar adaş yordam olamazlar. Olamamalarının sebebi, Java�nın bu yordamları dönüş tiplerine göre ayırt edememesinden kaynaklanır.

Arayüzün (Interface) İçerisinde Alan Tanımlama

Arayüzlerin içerisinde gövdesiz (soyut) yordamların dışında alanlarda bulunabilir. Bu alanlar uygulamalarda sabit olarak kullanabilir. Çünkü arayüzün içerisinde tanımlanan bir alan (ilkel tipte veya sınıf tipinde olsun) otomatik olarak hem public erişim belirleyicisine hemde final ve static özelliğine sahip olur.

AyBul.java
interface Aylar {
int
OCAK = 1, SUBAT = 2, MART = 3,
NISAN = 4, MAYIS = 5, HAZIRAN = 6, TEMMUZ = 7,
AGUSTOS = 8, EYLUL = 9, EKIM = 10,
KASIM = 11, ARALIK = 12;
}

public class AyBul {
public static **** main(String args[]) {

int ay = (int)(Math.random()*13) ;
System.out.println("Gelen ay = " + ay);
switch ( ay ) {
case Aylar.OCAK : System.out.println("Ocak");break;
case Aylar.SUBAT : System.out.println("Subat");break;
case Aylar.MART : System.out.println("Mart");break;
case Aylar.NISAN : System.out.println("Nisan");break;
case Aylar.MAYIS : System.out.println("Mayis");break;
case Aylar.HAZIRAN : System.out.println("Haziran");break;
case Aylar.TEMMUZ : System.out.println("Temmuz");break;
case Aylar.AGUSTOS : System.out.println("Agustos");break;
case Aylar.EYLUL : System.out.println("Eylul");break;
case Aylar.EKIM : System.out.println("Ekim");break;
case Aylar.KASIM : System.out.println("Kasim");break;
case Aylar.ARALIK : System.out.println("Aralik");break;
defaultystem.out.println("Tanimsiz Ay");
}
}
}
Arayüzün İçerisinde Tanımlanmış Alanlara İlk Değerlerinin Verilmesi

Arayüzlerin içerisinde tanımlanmış alanların ilk değerleri, çalışma anında da (run-time) verilebilir. Aşağıdaki örneği inceleyelim.

Test.java
interface A7 {

int devir_sayisi = (int) ( Math.random() *6 ) ;
String isim = "A7" ;
double t1 = ( Math.random() * 8 ) ;
}

public class Test {
public static **** main(String args[] ) {

System.out.println("devir_sayisi = " + A7.devir_sayisi );
System.out.println("isim = " + A7.isim );
System.out.println("t1 = " + A7.t1 );
}
}
A7 arayüzünün içerisindeki ilkel (primitive) int tipindeki devir_sayisi ve t1 alanlarının değerlerini derleme anında bilebilmek imkânsızdır. Bu değerler ancak çalışma anında bilenebilir.

Dikkat edilmesi gereken bir başka husus ise A7 arayüzünün içerisindeki alanların ne zaman ilk değerlerini aldıklarıdır. Bir arayüzün içerisindeki alanlar final ve statik oldukları için, A7 arayüzüne ilk kez erişildiği zaman, A7 arayüzünün içerisindeki tüm alanlar ilk değerlerini alırlar.

Genel Bakış

Arayüzler ve soyut sınıfların bizlere sağlamak istediği fayda nedir? Aslında ulaşılmak istenen amaç çoklu yukarı çevirimdir (upcasting). Bir sınıfa ait nesnenin birçok tipteki sınıf referansına bağlanabilmesi, uygulama içerisinde büyük esneklik sağlar. Bir örnek üzerinde açıklayalım�

GenelBakis.java
interface Arayuz1 {
public **** a1() ;
}

interface Arayuz2 {
public **** a2() ;
}

abstract class Soyut1 {
public abstract **** s1();
}

class A extends Soyut1 implements Arayuz1, Arayuz2 {
public **** s1() { // iptal etti (override)
System.out.println("A.s1()");
}
public **** a1() { // iptal etti (override)
System.out.println("A.a1()");
}
public **** a2() { // iptal etti (override)
System.out.println("A.a2()");
}
}
public class GenelBakis {
public static **** main(String args[]) {
Soyut1 soyut_1 = new A();
Arayuz1 arayuz_1 = (Arayuz1) soyut_1 ;
Arayuz2 arayuz_2 = (Arayuz2) soyut_1 ;
// Arayuz2 arayuz_2 = (Arayuz2) arayuz_1 ; // dogru

soyut_1.s1();
// soyut_1.a1(); // ! Hata !
// soyut_1.a2(); // ! Hata !

arayuz_1.a1();
// arayuz_1.a2(); // ! Hata !
// arayuz_1.s1(); // ! Hata !

arayuz_2.a2();
// arayuz_2.a1(); // ! Hata !
// arayuz_2.s1(); // ! Hata !
}
}
A sınıfı Soyut1 soyut sınıfından türetilmiştir, ayrıca A sınıfı Arayuz1 ve Arayuz2 arayüzlerine (interface) erişmektedir. Daha yakından incelenirse,

class A extends Soyut1 implements Arayuz1, Arayuz2 {
Yukarıdaki gösterim şunu der: A sınıfına ait bir nesne, Soyut1 sınıfı, Arayuz1 veya Arayuz2 arayüzü tipindeki referanslara bağlanabilir. Anlatılanlar UML diyagramına dönüştürülürse;

__________________

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.

Standart #2
Üyelik Tarihi: 10 Eylül 2012
Mesajlar: 3.858
Aldığı Beğeni: 1
Beğendikleri: 0
23 Ekim 2012 , 18:35
Alıntı ile Cevapla
Daha fazla yazi gorebilmek icin UYE OLmalisin.
Bu örneğimizde görüldüğü üzere, A sınıfı ait tek bir nesne oluşturulmuştur. Oluşturulan nesne farklı referanslara bağlanabilmektir.

Soyut1 soyut_1 = new A();
Arayuz1 arayuz_1 = (Arayuz1) soyut_1 ; // tip degisimi
Arayuz2 arayuz_2 = (Arayuz2) soyut_1 ; // tip degisimi
Oluşturulan tek bir A sınıfına ait nesne, birçok farklı sınıf ve arayüz tipindeki referansa bağlanabilmektedir. Örneğin yukarıdaki gösterimde, A sınıfına ait nesnemiz ilk olarak Soyut1 sınıfı tipindeki referansa bağlanmıştır. Bağlanabilir çünkü A sınıfı Soyut1 sınıfından türemiştir. Soyut1 sınıfı tipindeki referansa bağlı olan A sınıfına ait nesnenin sadece s1() yordamına ulaşılabilir.

Daha sonra Soyut1 referansının bağlı olduğu A sınıfına ait nesneyi, Arayuz1 tipindeki referansa bağlanıyor ama bu bağlama sırasında A sınıfına ait nesneyi Arayuz1 tipindeki referansa bağlanacağını açık açık söylemek gerekir. A sınıfına ait nesnemiz Arayuz1 tipindeki referansa bağlanırsa bu nesnenin sadece a1() yordamına erişilebilir.

Aynı şekilde Soyut1 sınıfı tipindeki referansa bağlı olan A sınıfına ait nesne, Arayuz2 tipindeki referansa bağlınabilir. A sınıfına ait nesne, Arayuz2 tipindeki referansa bağlanırsa, bu nesnenin sadece a2() yordamına erişebilir.

Soyut1 soyut_1 = new A();
Arayuz1 arayuz_1 = new A();
Arayuz2 arayuz_2 = new A();
Görüldüğü üzere, A sınıfına ait üç adet nesne oluşturduk ve bu nesnelerin her birini farklı tipteki referanslara bağlayabildik. Bu olay nesneye yönelik tasarımlar yaparken işimize çokça yarayabilecek bir yaklaşımdır.

Dâhili Arayüzler (Nested Interface)

Bir arayüz, başka bir arayüzün veya sınıfın içerisinde tanımlanabilir. Bir arayüzün içerisinde tanımlanan dâhili arayüzler, protected, friendly veya private erişim belirleyicisine sahip olamaz. Örneğimize geçmeden evvel UML diyagramını inceleyelim.



UML diyagramımızdan anlaşılacağı üzere, ArayuzA arayüzünün içerisinde iki adet dâhili arayüz (nested interface) tanımlanmıştır. Dışarıdaki iki sınıfımız, dâhili olarak tanımlanmış bu iki arayüze erişebilmektedir.

DahiliArayuzTest.java

interface ArayuzA { //aslinda public erisim belirleyicisine sahip
public interface DahiliArayuz1 {
public **** isYap1() ;
}

/* // ! Hata !
protected interface DahiliArayuz2 {
public **** isYap2() ;
}
*/

interface DahiliArayuz3 { // aslinda public erisim belirleyicisine sahip
public **** isYap3() ;
}

/* // ! Hata !
private interface DahiliArayuz4 {
public **** isYap4() ;
}
*/
}

class Erisim1 implements ArayuzA.DahiliArayuz1 {
public **** isYap1() {
System.out.println("Erisim1.isYap1()");
}
}

class Erisim2 implements ArayuzA.DahiliArayuz3 {
public **** isYap3() {
System.out.println("Erisim1.isYap3()");
}
}

public class DahiliArayuzTest {
public static **** main(String args[]) {
Erisim1 e1 = new Erisim1();
Erisim2 e2 = new Erisim2();
e1.isYap1();
e2.isYap3();
}
}
Dâhili arayüzlere erişen sınıflar açısından olaylar aynıdır. Yine bu dahili arayüzlerin içerisindeki gövdesiz yordamları iptal etmeleri gerekmektedir. Uygulamanın çıktısı aşağıdaki gibidir;

Erisim1.isYap1()
Erisim1.isYap3()

Sınıfların İçerisinde Tanımlanan Dahili Arayüzler (Nested Interface)

Bir arayüz diğer bir arayüzün içerisinde tanımlandığı gibi, bir sınıfın içerisinde de tanımlanabilir.

SinifA.java
public class SinifA {

public interface A1 {
public **** ekranaBas();
} //arayüz

public class DahiliSinif1 implements A1 {
public **** ekranaBas() {
System.out.println("DahiliSinif1.ekranaBas()");
}
} // class DahiliSinif1

protected class DahiliSinif2 implements A1 {
public **** ekranaBas() {
System.out.println("DahiliSinif2.ekranaBas()");
}
} // class DahiliSinif2

class DahiliSinif3 implements A1 {
public **** ekranaBas() {
System.out.println("DahiliSinif3.ekranaBas()");
}
} // class DahiliSinif3

private class DahiliSinif4 implements A1 {
public **** ekranaBas() {
System.out.println("DahiliSinif4.ekranaBas()");
}
} // class DahiliSinif4

public static **** main(String args[]) {
SinifA.DahiliSinif1 sad1 = new SinifA().new DahiliSinif1();
SinifA.DahiliSinif2 sad2 = new SinifA().new DahiliSinif2();
SinifA.DahiliSinif3 sad3 = new SinifA().new DahiliSinif3();
SinifA.DahiliSinif4 sad4 = new SinifA().new DahiliSinif4();

sad1.ekranaBas();
sad2.ekranaBas();
sad3.ekranaBas();
sad4.ekranaBas();

SinifB sb = new SinifB();
sb.ekranaBas();
}
}

class SinifB implements SinifA.A1{
public **** ekranaBas() {
System.out.println("SinifB.ekranaBas()");
}
}
SinifA sınıfının içerisinde tanımlanan A1 arayüzüne, SinifB sınıfından ulaşılabilir. Bir sınıfın içerisinde dahili arayüz tanımlanabildiği gibi dahili sınıfta tanımlanabilir. Bu konu az sonra incelenecektir. Bu örneğimizdeki ana fikir, bir sınıfın içerisinde nasıl dahili arayüzün oluşturulduğu ve bu dahili arayüzün, dahili sınıf olsun veya dışarıdan başka bir sınıf tarafından olsun, nasıl erişilebildiğini göstermektir.

Toparlamak gerekirse bu makalemizde Java ise arayüz kavramını ayrıntılı bir biçimde incelemeye çalıştık. Bir sonraki Java makalemizde ise Java ile dahili sınıflar kavramına ayrıntılı bir biçimde değinmeye çalışacağız.

Umarım Yararlı olmuştur.
__________________

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.

« Önceki Konu Sonraki Konu »

Şu an bu konuyu okuyan kişi sayısı: 1 (0 üye ve 1 misafir)