---
title: 'Soyut Sınıflar ve Arayüzler'
source: 'https://academia.sh/tr/kurslar/java-nesne-modeli/soyut-siniflar-ve-arayuzler'
course: 'Nesneye Dayalı Java'
language: tr
updated: '2026-08-17T18:09:40+00:00'
license: 'CC BY-SA 4.0'
---

# Soyut Sınıflar ve Arayüzler

Aynı yetenek sekiz ayrı yoldan kurulduğunda derleme üçünde duruyor; kalan beşte derleyici kararı kendisi veriyor ve tarafı hiç sormuyor — sınıf gövdesi arayüz varsayılanını yener, alt arayüz üsttekini yener, yalnız iki bağımsız arayüz aynı varsayılanı verdiğinde reddeder. Durum taşıyan bir yetenek arayüzle kurulamaz.

Önceki ders sekiz kararı tek bir referans üzerinde okudu ve tablodaki ikinci satır bir
arayüzden geliyordu: `Tasiyici` arayüzünün varsayılan yöntemi de yeniden tanımlanabiliyor ve
kararı çalışma zamanı tipi veriyordu. Arayüzün kendisi ise yalnız bir satır olarak geçti.

Bu ders onu konu yapar. Java'da bir yetenek iki ayrı araçla kurulabilir: gövdesi eksik bir
**soyut sınıf** ya da bir **arayüz**. İkisi de aynı işi görüyor gibi durur, ve seçim
çoğunlukla bir tasarım tercihi diye anlatılır. Ölçüm başka bir şeye bakar: **derleyici hangi
kurulumu reddediyor, ve reddetmediğinde kararı kime bırakıyor?**

Programlama Paradigmaları kursu arayüz ile soyut sınıf arasındaki seçimi tasarım gerekçeleriyle
karşılaştırmıştı; o gerekçeler tekrarlanmaz. Burada sayılan şey derleyicinin durduğu
noktalardır.

## İki Araç, İki Ayrı Kısıt

Soyut sınıf bir sınıftır: alan taşır, yapıcısı vardır, gövdeli ve gövdesiz yöntemleri yan
yana koyabilir. Karşılığında Java'nın tek üstlü kalıtımına bağlıdır — bir sınıf yalnız bir
sınıfı genişletebilir.

Arayüz tersini yapar. Bir sınıf istediği kadar arayüzü gerçekleştirebilir, dolayısıyla
yetenekler bir sınıfa yan yana takılabilir. Karşılığında arayüz **örnek durumu tutamaz**:
alan bildirimleri örtük olarak sabittir. Varsayılan yöntemler arayüze gövde koyma imkânı
verir, ama üzerinde çalışacak bir durum vermez.

Bu iki kısıt bir araya geldiğinde bir soru doğar. Çoklu gerçekleştirme serbestse, iki ayrı
arayüz **aynı imzayla** gövdeli birer yöntem verdiğinde ne olur? Kalıtımda böyle bir durum
yoktur, çünkü üst yalnız bir tanedir. Ölçüm buraya bakar.

## Ölçüm Çekirdeği

Ölçümün birinci yarısı hiçbir şey çalıştırmaz: her kurulum bir kaynak metnidir, derleyici
program içinden çağrılır ve yalnız çıkış durumu okunur.

- **SN16** — Sekiz kurulumun hepsi aynı yeteneği kurar: `tasi` adlı, dizgi döndüren tek bir
  yöntem. Değişen tek şey yeteneğin hangi tip biçimiyle verildiğidir.
- **SN17** — Derleyicinin ürettiği iletiler yutulur; okunan tek şey kaynağın kabul edilip
  edilmediğidir.

```java
// Derle.java — verilen kaynağın derlenip derlenmediğini söyler
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.file.*;
import java.util.spi.ToolProvider;

class Derle {
    static String olur(String kaynak) throws Exception {
        Path d = Files.createTempDirectory("soyut");
        Path k = d.resolve("Deneme.java");
        Files.writeString(k, kaynak);
        PrintWriter bos = new PrintWriter(Writer.nullWriter());
        return ToolProvider.findFirst("javac").orElseThrow()
                .run(bos, bos, "-d", d.toString(), k.toString()) == 0
                ? "derlendi" : "derlenmedi";
    }
}
```

## Sekiz Kurulum, Derleme Kaçında Duruyor

```java
// Kurulum.java — aynı yetenek sekiz ayrı yoldan kuruluyor, kaçı derleniyor
public class Kurulum {
    static final String[][] DENEME = {
        { "tek soyut sinifi genisletme",
          "abstract class A { abstract String tasi(); }\nclass C extends A { public String tasi() { return \"c\"; } }" },
        { "iki soyut sinifi genisletme",
          "abstract class A { }\nabstract class B { }\nclass C extends A, B { }" },
        { "soyut yontemi gerceklestirmeme",
          "abstract class A { abstract String tasi(); }\nclass C extends A { }" },
        { "iki arayuzu gerceklestirme",
          "interface A { default String tasi() { return \"a\"; } }\ninterface B { default String ad() { return \"b\"; } }\nclass C implements A, B { }" },
        { "iki arayuz ayni varsayilan, cozumsuz",
          "interface A { default String tasi() { return \"a\"; } }\ninterface B { default String tasi() { return \"b\"; } }\nclass C implements A, B { }" },
        { "iki arayuz ayni varsayilan, sinif cozer",
          "interface A { default String tasi() { return \"a\"; } }\ninterface B { default String tasi() { return \"b\"; } }\nclass C implements A, B { public String tasi() { return \"c\"; } }" },
        { "arayuz ile soyut sinif ayni yontem",
          "interface A { default String tasi() { return \"a\"; } }\nabstract class S implements A { public String tasi() { return \"s\"; } }\nclass C extends S { }" },
        { "alt arayuz ustteki varsayilani ezer",
          "interface A { default String tasi() { return \"a\"; } }\ninterface B extends A { default String tasi() { return \"b\"; } }\nclass C implements B { }" },
    };

    public static void main(String[] args) throws Exception {
        System.out.printf("%-40s %s%n", "kurulum", "sonuc");
        int durdu = 0;
        for (String[] d : DENEME) {
            String s = Derle.olur(d[1] + "\n");
            if (s.equals("derlenmedi")) durdu++;
            System.out.printf("%-40s %s%n", d[0], s);
        }
        System.out.println("derlemenin durdugu kurulum sayisi: " + durdu + " / " + DENEME.length);
    }
}
```

```
kurulum                                  sonuc
tek soyut sinifi genisletme              derlendi
iki soyut sinifi genisletme              derlenmedi
soyut yontemi gerceklestirmeme           derlenmedi
iki arayuzu gerceklestirme               derlendi
iki arayuz ayni varsayilan, cozumsuz     derlenmedi
iki arayuz ayni varsayilan, sinif cozer  derlendi
arayuz ile soyut sinif ayni yontem       derlendi
alt arayuz ustteki varsayilani ezer      derlendi
derlemenin durdugu kurulum sayisi: 3 / 8
```

Sekiz kurulumun **üçünde** derleme duruyor, **beşinde** sürüyor. Duran üçü ayrı nedenlerle
duruyor ve üçü de bu dersin iki aracını tanımlıyor.

İkinci satır soyut sınıfın kısıtıdır: iki sınıfı birden genişletmek yazılamıyor bile. Tek
üstlü kalıtım bir tasarım önerisi değil, dilin reddettiği bir yazımdır. Üçüncü satır soyut
sınıfın sözleşmesidir: gövdesiz bırakılan yöntem alt sınıfta doldurulmadığında sınıf somut
olamaz. Soyut sınıf bir eksiklik bildirir ve eksikliğin kapatılmasını derleme zamanında
zorlar.

Beşinci satır ise arayüzün karşılığıdır ve bu dersin çekirdek ölçümüdür. İki bağımsız arayüz
aynı imzayla gövdeli birer yöntem verdiğinde derleyici **karar vermeyi reddediyor.** Ortada
bir belirsizlik yoktur ki çözülsün — iki aday da eşit uzaklıktadır, ve dil aralarında bir
öncelik tanımlamak yerine kaynağı geri çeviriyor. Kalıtımda bu durum hiç doğmaz; çoklu
gerçekleştirmenin bedeli tam olarak budur.

Altıncı satır bedelin nasıl ödendiğini gösteriyor. Aynı iki arayüz, aynı çakışma — ama sınıf
kendi gövdesini yazdığında kaynak **derleniyor**. Derleyicinin istediği şey adaylardan birini
seçmek değil, seçimin **kaynakta yazılmasıdır.**

Derlenen satırların en sade ikisi, iki aracın neden yan yana durduğunu söylüyor. Birinci satır
soyut sınıfın verdiğidir: eksik bırakılan yöntem alt sınıfta doldurulunca sınıf somut olur ve
zincir kurulur. Dördüncü satır arayüzün verdiğidir: `C` sınıfı iki ayrı yeteneği aynı anda
üstleniyor ve ikisi de imzalarıyla çakışmadığı için ortada soru yoktur. Çakışma bir kural
değil, bir **kesişme** durumudur; yalnız iki bağımsız arayüz aynı imzayı verdiğinde doğar.
Ölçümün geri kalanı o kesişmenin nasıl kapatıldığını sayar.

## Derleme Durmadığında Kim Kazanıyor

Kalan beş kurulumun üçünde ortada birden fazla aday vardır ve derleme yine de sürüyor. Bu
durumlarda kararı kim veriyor?

- **SN18** — Üç kurulumda da çağrı, bildirilen tipi `Tasiyici` olan bir referans üzerinden
  yapılır; değişen tek şey çalışma zamanı tipini kuran tip hiyerarşisidir.
- **SN19** — Her gövde kendi kaynağını metin olarak döndürür; kazanan taraf çıkarımla değil,
  dönen değerden okunur.

```java
// Tasiyici.java — aynı yeteneği iki yoldan veren tipler
interface Tasiyici {
    default String tasi() { return "arayuz varsayilani"; }
}

interface Etiketli extends Tasiyici {
    @Override default String tasi() { return "alt arayuz varsayilani"; }
}

interface Ikinci {
    default String tasi() { return "ikinci arayuz varsayilani"; }
}

abstract class SoyutTasiyici implements Tasiyici {
    @Override public String tasi() { return "soyut sinif govdesi"; }
    abstract String ad();
}

class Ozgul implements Etiketli { }

class SinifKazanir extends SoyutTasiyici implements Tasiyici {
    @Override String ad() { return "sinif"; }
}

class Cozen implements Tasiyici, Ikinci {
    @Override public String tasi() { return "sinif kendi cozdu"; }
}

class Secen implements Tasiyici, Ikinci {
    @Override public String tasi() { return Ikinci.super.tasi(); }
}
```

```java
// Kazanan.java — derleme durmadığında hangi taraf kazanıyor
public class Kazanan {
    public static void main(String[] args) {
        Tasiyici a = new Ozgul();
        Tasiyici b = new SinifKazanir();
        Tasiyici c = new Cozen();
        Tasiyici e = new Secen();
        System.out.printf("%-36s %s%n", "kaynak", "tasi() sonucu");
        System.out.printf("%-36s %s%n", "arayuz, ustteki ve alttaki", a.tasi());
        System.out.printf("%-36s %s%n", "arayuz varsayilani ve sinif govdesi", b.tasi());
        System.out.printf("%-36s %s%n", "iki bagimsiz arayuz, sinif cozer", c.tasi());
        System.out.printf("%-36s %s%n", "iki bagimsiz arayuz, sinif secer", e.tasi());
    }
}
```

```
kaynak                               tasi() sonucu
arayuz, ustteki ve alttaki           alt arayuz varsayilani
arayuz varsayilani ve sinif govdesi  soyut sinif govdesi
iki bagimsiz arayuz, sinif cozer     sinif kendi cozdu
iki bagimsiz arayuz, sinif secer     ikinci arayuz varsayilani
```

Dört satır, dört ayrı seçim ve yalnız son ikisi kaynakta yazılıdır.

İlk satırda iki arayüz vardır, ama biri ötekini genişletiyor. Bu bir çakışma değildir:
`Etiketli`, `Tasiyici`'nin varsayılanını **yeniden tanımlar** ve daha özgül olan kazanır. Kural
kalıtımdaki kuralın aynısıdır; iki tip arasında bir alt–üst ilişkisi varsa alttaki seçilir.

İkinci satır dilin sessiz önceliğidir. `SinifKazanir` hem soyut sınıftan bir gövde, hem
arayüzden bir varsayılan alıyor. Kaynakta bir seçim yazılı değildir, buna karşın derleme
duruyor ve sonuç **soyut sınıf gövdesi** çıkıyor. Sınıf hattından gelen gövde arayüz
varsayılanını her zaman yener. Bu kural bir belirsizliği çözer, ama çözdüğünü kimseye
sormaz — arayüzü yazan taraf gövdesinin çağrılmadığını hiçbir yerde göremez.

Üçüncü satır ise beşinci kurulumun derlenen biçimidir. `Cozen` iki bağımsız arayüzü
gerçekleştiriyor ve kendi gövdesini yazıyor; kazanan **kaynakta yazılan** taraftır. Burada
çakışma çözülmemiş, yalnız aşılmıştır: iki varsayılan gövdenin ikisi de çağrılmıyor.

Dördüncü satır çakışmanın asıl çözümüdür. `Secen` de kendi gövdesini yazıyor, ama gövdesinde
adaylardan birini adıyla çağırıyor — sonuç **ikinci arayuz varsayilani**. Derleyicinin istediği
şey yeni bir davranış değildi; **hangi adayın seçildiğinin yazılmasıydı**, ve dil bu seçimi
yazmak için bir biçim veriyor. Reddedilen kaynak ile kabul edilen kaynak arasındaki fark bir
gerçekleştirim değil, bir imzadır.

Buradan dersin ana okuması çıkıyor. Derleyici üç ayrı davranış gösteriyor: bir hiyerarşi
varsa en özgülü seçer, sınıf ile arayüz karşılaştığında sınıfı seçer, iki eşit arayüz
karşılaştığında seçmez. Yalnız sonuncusu programcıya görünür. İlk ikisi de birer karardır ve
ikisi de bildirilen tiplerin hiyerarşisine bakılarak **derleme zamanında** verilir; çalışma
zamanı tipinin buradaki payı, hangi gövdenin çağrılacağını değil, o gövdeyi taşıyan sınıfın
ne olduğunu belirlemekle sınırlıdır.

## Sınırlayıcı Ölçüm: Durum Taşıyan Yetenek Arayüzle Kurulamaz

Tablo arayüzü çoklu gerçekleştirme yüzünden daha esnek gösteriyor. Sınır, arayüzün ne
tutamadığındadır.

- **SN20** — Üç kurulumun üçü de aynı yeteneği kurar: bir sayacı bir artıran tek bir işlem.
  Değişen tek şey sayacın nerede tutulduğudur.

```java
// Durum.java — durum taşıyan bir yetenek hangi araçla kurulabiliyor
public class Durum {
    static final String[][] DENEME = {
        { "arayuzde sabit bildirimi",
          "interface Sayac { int BASLANGIC = 0; }" },
        { "arayuzde ornek alani ve artirma",
          "interface Sayac { int deger = 0; default void artir() { deger++; } }" },
        { "soyut sinifta alan ve artirma",
          "abstract class Sayac { int deger = 0; void artir() { deger++; } }" },
    };

    public static void main(String[] args) throws Exception {
        System.out.printf("%-36s %s%n", "yetenek nasil kuruluyor", "sonuc");
        for (String[] d : DENEME)
            System.out.printf("%-36s %s%n", d[0], Derle.olur(d[1] + "\n"));
        System.out.println();
        Adet x = new Adet(), y = new Adet();
        x.artir(); x.artir(); y.artir();
        System.out.println("soyut siniftan turetilen iki ornek : " + x.deger + " ve " + y.deger);
        System.out.println("arayuzdeki sabit ornek olmadan okunur: " + Sabitli.BASLANGIC);
    }
}

abstract class SoyutSayac {
    int deger = 0;
    void artir() { deger++; }
}

class Adet extends SoyutSayac { }

interface Sabitli { int BASLANGIC = 0; }
```

```
yetenek nasil kuruluyor              sonuc
arayuzde sabit bildirimi             derlendi
arayuzde ornek alani ve artirma      derlenmedi
soyut sinifta alan ve artirma        derlendi

soyut siniftan turetilen iki ornek : 2 ve 1
arayuzdeki sabit ornek olmadan okunur: 0
```

İlk satır yanıltıcıdır: arayüzde bir alan bildirilebiliyor. İkinci satır onun ne olduğunu
söylüyor — o alan artırılamaz, çünkü örtük olarak sabittir. Arayüzde yazılan her alan
bildirimi, yazılmasa da, sınıf düzeyinde ve değiştirilemezdir. Son satırın gösterdiği gibi
hiçbir örnek kurulmadan okunabiliyor, yani bir örneğe ait değildir.

Üçüncü satır ile alttaki koşum karşı tarafı ölçüyor. Aynı yetenek soyut sınıfla kurulduğunda
derleniyor ve iki örnek **2** ile **1** sayıyor: her nesnenin kendi sayacı var. Yeteneğin
gerektirdiği şey bir gövde değil, gövdenin üzerinde çalışacağı **örneğe ait bir yerdi**, ve
arayüz o yeri veremiyor. İki sayının ayrı çıkması ölçümün kendisidir: tek bir yer paylaşılsaydı
her iki referans da **3** okurdu.

Sınırın anlamı, dersin ilk yarısındaki esnekliği tersine çeviriyor. Arayüz çoklu takılabilir
olduğu için daha geniş görünür; oysa taşıyabildiği şey yalnız davranıştır. Bir yetenek durum
tutuyorsa çoklu gerçekleştirme zaten sorulamaz, çünkü tek aday vardır. İki aracın seçimi bir
üslup sorusu değildir: yetenek durumsuzsa iki yol da açıktır ve arayüz çoklu takılmayı
kazandırır; yetenek durum tutuyorsa yol tektir ve onunla birlikte tek üstlü kalıtımın kısıtı
da gelir.

## Özet

- Aynı yeteneğin sekiz kurulumundan **üçünde** derleme durur: iki sınıfı birden genişletmek,
  soyut yöntemi doldurmamak, ve iki bağımsız arayüzün aynı varsayılanı vermesi.
- İki bağımsız arayüz aynı imzayla gövde verdiğinde derleyici **karar vermeyi reddeder**;
  aynı kaynak, sınıf kendi gövdesini yazdığında derlenir. İstenen şey yeni bir davranış
  değil, seçimin kaynakta yazılmasıdır — sınıf adaylardan birini adıyla da çağırabilir.
- Derleme durmadığında karar yine derleyicinindir ve sessizdir: hiyerarşi varsa **en özgül**
  arayüz kazanır, sınıf ile arayüz karşılaştığında **sınıf gövdesi** kazanır.
- Sessiz kararın bedeli görünmezliğidir: arayüz varsayılanını yazan taraf, gövdesinin hiç
  çağrılmadığını kendi kaynağına bakarak göremez.
- Arayüzde bildirilen alan örtük olarak sabittir ve örnek olmadan okunur; artırılmaya
  çalışıldığında kaynak **derlenmez**.
- Aynı sayaç soyut sınıfla kurulduğunda iki örnek **2** ile **1** sayar: durum taşıyan bir
  yetenek arayüzle kurulamaz, ve o yolu seçmek tek üstlü kalıtımın kısıtını da getirir.

## Sonraki Adım

Bu derste iki soyutlama aracı da **örnek** düzeyinde çalışıyordu: soyut sınıfın gövdesi de,
arayüzün varsayılan yöntemi de bir nesne üzerinden çağrıldı ve hangi gövdenin yürütüleceği
sorusu hep bir örneğin çalışma zamanı tipiyle birlikte soruldu. Sıradaki ders sınıfın
kendisine ait üyelere bakar ve kararın tarafının orada ters döndüğünü ölçer.
