---
title: 'Arayüz Gömme'
source: 'https://academia.sh/tr/kurslar/go-tip-sistemi/arayuz-gomme'
course: 'Arayüzler, Hatalar ve Genellikler'
language: tr
updated: '2026-08-23T14:25:02+00:00'
license: 'CC BY-SA 4.0'
---

# Arayüz Gömme

Gömme, iki arayüzü kaynakta tek bir bileşik sözleşmede birleştiriyor ve bu birleşim hiçbir yeni yöntem eklemiyor: gömme ile kurulan ve elle yeniden yazılan aynı sözleşme, aynı iki yöntemi istiyor. Bileşik arayüzü karşılamak için bir tipin yazması gereken yöntem sayısı, gömülen arayüzlerin toplam yöntem sayısına eşit, ne fazla ne eksik. Sınırlayıcı ölçüm: gömme yalnız sözleşmeyi birleştiriyor, gerçekleştirimi birleştirmiyor — iki ayrı tip iki ayrı sözleşmeyi ayrı ayrı karşılayabiliyor ama bileşik sözleşmeyi hiçbiri karşılamıyor.

Önceki ders bir tipin birden çok sözleşmeyi aynı anda karşılayabildiğini gördü, ama her
sözleşme kaynakta ayrı ayrı duruyordu. Bir tip hem depolayabilmeli hem kapatılabilmeli
gerektiğinde, bu iki isteği tek bir adla anmanın bir yolu gerekiyor. Gömme bu yolu
sağlıyor: bir arayüz, başka arayüzleri kendi gövdesine yalnızca adlarını yazarak alabiliyor.
Bu, önceki üç dersteki bağların hiçbirine benzemiyor — kaynakta açıkça yazılı, dolayısıyla
**bildirim** sınıfının en açık örneği.

İlk dersteki on altı bağın yalnız dördü bildirimdeydi ve ikisi zaten gömmeyle ilgiliydi:
`Gomulu`nun kendisi ve onu karşıladığını doğrulayan derleme zamanı kanıtı. Bu ders o iki
satırı büyütüp gömmenin kendi kurallarını ölçüyor — ne birleştirdiğini, ne kadarını
birleştirdiğini, ve nerede durduğunu. Üç ölçüm bu sırayla ilerliyor: önce gömmenin gerçekten
yeni bir yöntem eklemediği doğrulanıyor, sonra bileşik sözleşmeyi karşılamanın en az kaç
yöntem gerektirdiği bulunuyor, son olarak bu birleşmenin nerede durduğu — sözleşmede mi,
gerçekleştirimde mi — sınanıyor.

## Sözleşmeleri Kaynakta Birleştirmek

Bir arayüz gömmesi, bir arayüz gövdesinin içine başka bir arayüzün adını yazmaktan ibaret.
Sonuç, gömülen arayüzlerin yöntemlerinin tamamını isteyen yeni bir arayüz. Yazım kısa:
gömülen arayüzün önüne bir alan adı konmuyor, yalnız kendi adı bir satır olarak yazılıyor —
bu, gömmenin yapı gömmesinden ödünç aldığı aynı yazım kuralı, adlandırılmamış bir alanmış
gibi görünen ama bir tip adı olan bir satır. Aşağıdaki ölçüm aynı sözleşmeyi iki yoldan
kuruyor — biri gömerek, biri elle yeniden yazarak — ve ikisinin de istediği yöntem sayısını
`reflect` ile sayıyor.

```go
// esdegerlik.go — gomme ile kurulan sozlesme, elle yazilanla ayni yontem sayisini istiyor
package main

import (
	"fmt"
	"reflect"
)

type Okuyucu interface{ Oku() string }
type Yazici interface{ Yaz(m string) }

// Gomme: iki arayuz adi, gomulen arayuzun govdesine yaziliyor.
type OkuyupYazanGomulu interface {
	Okuyucu
	Yazici
}

// Ayni sozlesme, elle yeniden yazilmis.
type OkuyupYazanElle interface {
	Oku() string
	Yaz(m string)
}

func main() {
	a := reflect.TypeOf((*OkuyupYazanGomulu)(nil)).Elem()
	b := reflect.TypeOf((*OkuyupYazanElle)(nil)).Elem()

	fmt.Println("gomme ile istenen yontem sayisi   :", a.NumMethod())
	fmt.Println("elle yazilan istenen yontem sayisi:", b.NumMethod())
	for i := 0; i < a.NumMethod(); i++ {
		fmt.Println("  yontem:", a.Method(i).Name)
	}
}
```

```
gomme ile istenen yontem sayisi   : 2
elle yazilan istenen yontem sayisi: 2
  yontem: Oku
  yontem: Yaz
```

`OkuyupYazanGomulu` kaynakta yalnızca iki adı (`Okuyucu`, `Yazici`) taşıyor, hiçbir yöntem
imzası yazmıyor. Ama `reflect` ona sorulduğunda, tıpkı iki yöntemi elle yazan
`OkuyupYazanElle` gibi, tam iki yöntem istediğini söylüyor: `Oku` ve `Yaz`. Gömme bir
kısaltma — kaynakta daha az yazmayı sağlıyor — ama ürettiği sözleşme, elle yazılanla
**birebir aynı**. Bu, Go Temelleri kursunun Yapılar dersindeki gömme kavramının bir
uzantısı: orada bir yapı başka bir yapının alan ve yöntem adlarını yazılmadan taşıyordu,
burada bir arayüz başka bir arayüzün yöntem adlarını yazılmadan taşıyor. İkisi de aynı
sözcükle (**gömme**) anılıyor çünkü ikisi de aynı düzeneği kullanıyor: bir adı yazmak,
o adın taşıdığı her şeyi getiriyor.

**AR10.** `reflect.TypeOf((*T)(nil)).Elem()` yazımı, bir arayüz tipinin kendisini (bir arayüz
*değerini* değil) `reflect.Type` olarak elde etmenin standart yolu — `(*T)(nil)` bir işaretçi
değeri üretiyor, `.Elem()` bu işaretçinin gösterdiği arayüz tipine iniyor. Bu ölçüm boyunca
hiçbir gerçek `T` değeri oluşturulmuyor, yalnız tipin kendisi sorgulanıyor.

Gömme burada iki arayüzle sınırlı değil; gömülen bir arayüz kendisi de başka bir arayüz
gömebiliyor, ve zincir birkaç kademe uzayabiliyor. Aşağıdaki ölçüm `OkuyupYazanGomulu`yu
üçüncü bir arayüzle (`Kapatan`) daha gömerek bir kademe derinleştiriyor ve toplam yöntem
sayısının hâlâ doğru toplandığını sınıyor.

```go
// zincir.go — iki kademeli gomme, toplam yontem sayisini yine dogru topluyor
package main

import (
	"fmt"
	"reflect"
)

type Okuyucu interface{ Oku() string }
type Yazici interface{ Yaz(m string) }
type Kapatan interface{ Kapat() error }

type OkuyupYazan interface {
	Okuyucu
	Yazici
}

type TamKaynak interface {
	OkuyupYazan
	Kapatan
}

func main() {
	t := reflect.TypeOf((*TamKaynak)(nil)).Elem()
	fmt.Println("iki kademeli gomme, toplam yontem sayisi:", t.NumMethod())
	for i := 0; i < t.NumMethod(); i++ {
		fmt.Println("  yontem:", t.Method(i).Name)
	}
}
```

```
iki kademeli gomme, toplam yontem sayisi: 3
  yontem: Kapat
  yontem: Oku
  yontem: Yaz
```

`TamKaynak`, `OkuyupYazan`ı gömüyor, `OkuyupYazan` da kendi içinde `Okuyucu` ile `Yazici`yi
gömüyor — iki kademe. Toplam yöntem sayısı yine üç, tek tek gömülen üç yöntemin
(`Oku`, `Yaz`, `Kapat`) toplamı. Kademe sayısı arttıkça toplama kuralı değişmiyor: her
kademe kendi altındaki bütün adları yukarı taşıyor, hiçbir ad kaybolmuyor ve hiçbir ad
iki kez sayılmıyor.

Bu, `TamKaynak`ı okuyan birinin görmesi gereken şeyi netleştiriyor: kaynakta yalnız iki satır
(`OkuyupYazan`, `Kapatan`) var, ama sözleşme üç yöntem istiyor. Ara kademeyi (`OkuyupYazan`)
açmadan bu üç sayıyı kaynaktan çıkarmak mümkün değil — okuyucunun zincirin tamamını takip
etmesi gerekiyor. Gömme kaynağı kısaltıyor ama okuma yükünü aynı oranda azaltmıyor; kısa
kaynak, uzun bir sözleşmeyi hâlâ taşıyabiliyor.

## Kaç Yöntem Yazmak Gerekiyor

Gömme yöntem eklemediğine göre, bileşik bir arayüzü karşılamak için bir tipin yazması gereken
en az yöntem sayısı, gömülen arayüzlerin yöntemlerinin toplamı olmalı — ne bir fazla ne bir
eksik. `reflect` bunu bir arayüz **tipine** sorarak saydı; aşağıdaki ölçüm aynı soruyu bir
arayüz **tanımına karşı sınanan bir tipe** sorarak, derleyicinin kendisinden alıyor. İkisi
aynı sayıya varmalı: `reflect`in söylediği sayı, derleyicinin kabul ettiği en küçük sayı.

```go
// arac.go — bir kaynak parcasinin derlenip derlenmedigini programin icinden sinar
package main

import (
	"os"
	"os/exec"
	"path/filepath"
)

func derlenirMi(kaynak string) bool {
	dizin, err := os.MkdirTemp("", "sinama")
	if err != nil {
		return false
	}
	defer os.RemoveAll(dizin)
	os.WriteFile(filepath.Join(dizin, "go.mod"), []byte("module sinama\n\ngo 1.24\n"), 0o644)
	os.WriteFile(filepath.Join(dizin, "kod.go"), []byte(kaynak), 0o644)
	cmd := exec.Command("go", "build", "./...")
	cmd.Dir = dizin
	cmd.Env = append(os.Environ(), "GOTOOLCHAIN=local")
	return cmd.Run() == nil
}
```

```go
// kac-yontem.go — bilesik arayuzu karsilamak icin gereken en az yontem sayisi olculuyor
package main

import "fmt"

func main() {
	ortak := `package sinama

type Okuyucu interface{ Oku() string }
type Yazici interface{ Yaz(m string) }

type OkuyupYazan interface {
	Okuyucu
	Yazici
}

`
	sifirYontem := ortak + `type Aday struct{}

var _ OkuyupYazan = Aday{}
`
	birYontem := ortak + `type Aday struct{}
func (Aday) Oku() string { return "" }

var _ OkuyupYazan = Aday{}
`
	ikiYontem := ortak + `type Aday struct{}
func (Aday) Oku() string { return "" }
func (Aday) Yaz(m string) {}

var _ OkuyupYazan = Aday{}
`
	fmt.Println("sifir yontemle derleniyor mu:", derlenirMi(sifirYontem))
	fmt.Println("bir yontemle derleniyor mu  :", derlenirMi(birYontem))
	fmt.Println("iki yontemle derleniyor mu  :", derlenirMi(ikiYontem))
}
```

```
sifir yontemle derleniyor mu: false
bir yontemle derleniyor mu  : false
iki yontemle derleniyor mu  : true
```

Sıfır yöntemli aday derlenmiyor, çünkü ikisi de eksik. Bir yöntemli aday (yalnız `Oku`) da
derlenmiyor, çünkü `Yaz` hâlâ eksik — `Okuyucu`yu karşılamak `OkuyupYazan`ı karşılamak
anlamına gelmiyor, gömme bir arayüzü diğerinin yerine geçirmiyor, ikisini birlikte istiyor.
İki yöntemli aday derleniyor ve bu, tam olarak `reflect`in bir önceki bölümde saydığı sayı.
Üç aday, tek bir eşiği (iki yöntem) iki yönden de sınıyor: bir eksik yetmiyor, tam sayı
yetiyor.

Bu eşik, üçüncü dersteki küçük arayüz ölçümüyle aynı ekseni izliyor: bir arayüzün istediği
yöntem sayısı ne kadar büyükse, onu karşılayan tipin yükü o kadar ağır. Gömme burada
yöntem sayısını **azaltmıyor**; yalnız iki ayrı sözleşmeyi tek bir adla anmayı
kolaylaştırıyor. `OkuyupYazan`ı karşılamanın maliyeti, `Okuyucu`yu ve `Yazici`yi ayrı ayrı
karşılamanın maliyetinin toplamı — gömme bu toplamı düşürecek bir kısayol sunmuyor, yalnız
adlandırmayı tek bir noktada topluyor.

**AR11.** Üç aday da aynı `Aday` adını taşıyor ve aynı `OkuyupYazan`a karşı sınanıyor;
tek değişen, `Aday`ın kendi yöntem kümesi. Bu, üç ayrı ölçümü karşılaştırılabilir kılıyor —
fark yalnız bir değişkende, geri kalan her şey sabit. Aynı disiplin dördüncü bir adayla da
sınanabilirdi — üç yöntem yazan, ikisi `OkuyupYazan`ın istediği isimlerle eşleşen, üçüncüsü
fazladan bir yöntem olan bir tip. Böyle bir tip yine derlenirdi, çünkü arayüz karşılaması bir
**alt küme** ilişkisidir: tipin yöntem kümesi arayüzün istediğini kapsıyorsa, fazlası bir
sorun oluşturmuyor.

## Sınırlayıcı Ölçüm: Sözleşme Birleşir, Gerçekleştirim Birleşmez

Gömme kaynakta iki sözleşmeyi birleştiriyor, ama bu birleşme bir **gerçekleştirim** garantisi
vermiyor. Bileşik arayüzü karşılayan bir tip, gömülen iki arayüzü de ayrı ayrı karşılıyor —
bu yön kolay. Ama tersi doğru değil: iki ayrı tip, iki ayrı sözleşmeyi ayrı ayrı
karşılayabiliyor, bileşik sözleşmeyi ise hiçbiri karşılamıyor. Önceki bölümdeki eşik ölçümü
"kaç yöntem yeter" sorusunu bir tek tipin üzerinden sordu; bu ölçüm aynı soruyu birden çok
tip üzerinden sorup, tipler arasında hiçbir paylaşımın olmadığını gösteriyor.

```go
// iki-yon.go — bilesik sozlesmeyi karsilamanin iki yonu ayri ayri sinaniyor
package main

import "fmt"

type Okuyucu interface{ Oku() string }
type Yazici interface{ Yaz(m string) }

type OkuyupYazan interface {
	Okuyucu
	Yazici
}

type Dosya struct{}

func (Dosya) Oku() string  { return "icerik" }
func (Dosya) Yaz(m string) {}

type SadeceOkuyan struct{}

func (SadeceOkuyan) Oku() string { return "a" }

type SadeceYazan struct{}

func (SadeceYazan) Yaz(m string) {}

func main() {
	var d any = Dosya{}
	_, okurMu := d.(Okuyucu)
	_, yazarMi := d.(Yazici)
	_, bilesikMi := d.(OkuyupYazan)
	fmt.Println("ileri yon, Dosya Okuyucu mu       :", okurMu)
	fmt.Println("ileri yon, Dosya Yazici mi        :", yazarMi)
	fmt.Println("ileri yon, Dosya OkuyupYazan mi   :", bilesikMi)

	var okur any = SadeceOkuyan{}
	var yazar any = SadeceYazan{}
	_, okurTamam := okur.(Okuyucu)
	_, yazarTamam := yazar.(Yazici)
	_, okurBilesikMi := okur.(OkuyupYazan)
	_, yazarBilesikMi := yazar.(OkuyupYazan)
	fmt.Println("geri yon, SadeceOkuyan Okuyucu mu    :", okurTamam)
	fmt.Println("geri yon, SadeceYazan Yazici mi      :", yazarTamam)
	fmt.Println("geri yon, SadeceOkuyan OkuyupYazan mi:", okurBilesikMi)
	fmt.Println("geri yon, SadeceYazan OkuyupYazan mi :", yazarBilesikMi)
}
```

```
ileri yon, Dosya Okuyucu mu       : true
ileri yon, Dosya Yazici mi        : true
ileri yon, Dosya OkuyupYazan mi   : true
geri yon, SadeceOkuyan Okuyucu mu    : true
geri yon, SadeceYazan Yazici mi      : true
geri yon, SadeceOkuyan OkuyupYazan mi: false
geri yon, SadeceYazan OkuyupYazan mi : false
```

İleri yönde tek bir tip (`Dosya`) her üç arayüzü de karşılıyor — bileşik sözleşmeyi
karşılayan bir tip, parçalarını da otomatik olarak karşılıyor, çünkü bileşik sözleşmenin
yöntem kümesi parçaların üst kümesi. `Dosya`nın `Oku` ve `Yaz` yöntemlerini yazmış olması
tek başına yeterli; `Okuyucu`yu, `Yazici`yi ve `OkuyupYazan`ı ayrı ayrı karşılamak için üç
kez farklı kod yazmasına gerek kalmıyor.

Geri yönde durum farklı: `SadeceOkuyan` yalnız `Okuyucu`yu, `SadeceYazan` yalnız `Yazici`yi
karşılıyor ve ikisi de doğru. Ama `OkuyupYazan`ı karşılayan **hiçbiri** yok — ne
`SadeceOkuyan`, ne `SadeceYazan`. İki sözleşme ayrı ayrı karşılanmış olması, bileşik
sözleşmenin de karşılandığı anlamına gelmiyor; bunun için tek bir tipin **her iki** yöntemi
birden yazması gerekiyor. Programda `SadeceOkuyan` ve `SadeceYazan`ın ikisi birden var olsa
bile, `OkuyupYazan` isteyen bir yer bu ikisinden hiçbirini kabul etmiyor — ikisinin
"toplamı" diye bir şey tip sisteminde yok.

**AR12.** `SadeceOkuyan` ile `SadeceYazan`ın birlikte "bir yerlerde" `Oku` ve `Yaz`
yöntemlerinin ikisini de karşılıyor olması, programın hiçbir yerinde bir anlam taşımıyor —
Go'nun tip sistemi iki ayrı tipin yöntemlerini otomatik olarak birleştiren bir düzenek
sunmuyor. Gömme yalnız **arayüz tanımını** birleştiriyor; iki farklı somut tipin
davranışlarını birleştirmek isteyen bir üçüncü tip, kendi yöntemlerini kendisi yazmak ya da
K01'in Yapılar dersindeki gömme yoluyla iki somut tipi kendi içine almak zorunda.

Bu ayrım, yapı gömmesiyle arayüz gömmesi arasındaki temel farkı açıklıyor. Bir yapı başka
bir yapıyı gömdüğünde, gömülü tipin gerçek bir değeri — kendi alanları ve yöntemleriyle
birlikte — dış yapının içinde somut olarak duruyor; K01'in Yapılar dersinde gömülü
yöntemlerin dış tipten yazılmadan çağrılabilmesinin nedeni buydu. Bir arayüz başka bir
arayüzü gömdüğünde ise ortada hiçbir değer yok, yalnızca bir imza listesi birleşiyor. Arayüz
gömmesi bir değer taşımıyor, yalnızca bir istek taşıyor; bu isteği kimin karşılayacağı ayrı
bir soru, ve bu sorunun yanıtı yalnızca tek bir somut tipin kendi yöntemleriyle (ya da o
tipin kendi yapı gömmeleriyle) verilebiliyor. İki gömme de aynı sözcüğü paylaşıyor çünkü
ikisi de bir adı yazıp onun taşıdığı her şeyi kazanma fikrine dayanıyor; ama biri bir değeri
taşırken öbürü yalnızca bir sözleşmeyi taşıyor.

## Özet

- Arayüz gömme, bir arayüzün gövdesine başka arayüzlerin adlarını yazmaktan ibaret; bağ
  kaynakta açıkça duruyor, bu kursta bildirim sınıfının en açık örneği.
- Gömme ile kurulan bir sözleşme, aynı yöntemleri elle yeniden yazan bir sözleşmeyle
  `reflect` düzeyinde birebir aynı yöntem sayısını istiyor — gömme hiçbir yeni yöntem
  eklemiyor.
- Bileşik bir arayüzü karşılamak için bir tipin yazması gereken en az yöntem sayısı,
  gömülen arayüzlerin toplamına eşit: bir eksik yetmiyor, tam sayı yetiyor.
- Bileşik arayüzü karşılayan bir tip gömülen arayüzlerin her birini de karşılıyor, ama
  tersi doğru değil: iki ayrı tip iki sözleşmeyi ayrı ayrı karşılayıp bileşik sözleşmeyi
  hiçbiri karşılamayabiliyor.
- Arayüz gömmesi bir değer taşımıyor, yalnızca bir sözleşme taşıyor; yapı gömmesi (K01'in
  Yapılar dersi) ise gerçek bir değeri taşıyor — aynı sözcük, iki ayrı düzenek.

## Sonraki Adım

Bu derste sözleşmeyi tanımlayan taraf, sözleşmeyi karşılayacak tipten önce davranmıştı:
`Okuyucu` ve `Yazici`, `Dosya` yazılmadan önce zaten oradaydı. Ama üçüncü dersteki
`Depolayici` de, birinci dersteki `Kisa` da, karşıladıkları tipin kaynağında hiç
geçmiyordu — sözleşmeyi tanımlayan taraf, kullanan taraftı. Bu iki kalıp arasındaki fark bir
tesadüf değil, bir tercih: bazen sözleşmeyi üreten taraf yazar (bu ders), bazen tüketen
taraf (birinci ve üçüncü ders). Sıradaki ders bu tercihi bir tasarım kararına dönüştürüyor:
bir arayüzü kim tanımlamalı, üreten paket mi, tüketen taraf mı, ve bunun ölçülebilir bir
karşılığı var mı?
