---
title: 'İşleç Aşırı Yükleme'
source: 'https://academia.sh/tr/kurslar/rust-soyutlama/islec-asiri-yukleme'
course: "Trait'ler, Genellikler ve Hata Yönetimi"
language: tr
updated: '2026-09-13T05:09:26+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "Bir işlecin kullanımının, standart kitaplıktaki bir trait'in yöntem çağrısına karşılık geldiğini gösterir"
    - 'Zincirlenmiş bir işleç ifadesinde çağrı sayısının terim sayısından bir eksik olduğunu koşturarak doğrular'
    - 'İşlecin çağrı yerinin kaynakta görünmediğini, bu yüzden çağrı sayısının yalnız sayılarak bilinebildiğini açıklar'
---

# İşleç Aşırı Yükleme

Bir işlecin (+ gibi) her kullanımı, arkasında görünmeyen bir trait çağrısıdır; üç terimli bir toplam iki kez çağırır, beş terimli bir toplam dört kez — işlecin kısa sözdizimi çağrı sayısını değiştirmez, yalnız çağrının kaynakta görünür olup olmadığını değiştirir ve bu sayı ancak koşum defteriyle bilinebilir.

Önceki ders, kaynakta hiç yazılı olmayan bir gövdenin yine de çalıştığını gösterdi. Bu ders
tam tersi bir görünmezliğe bakıyor: gövde kaynakta yazılı, ama onu **çağıran satır** kaynakta
görünmüyor. `a + b` yazıldığında bir çağrı yapılıyor, ama kaynakta `add` adını taşıyan hiçbir
satır yok — çağrı, `+` işlecinin arkasına gizlenmiş. Nesneye Dayalı Java kursu işleç aşırı
yüklemeyi zaten tanımlamıştı; orada ölçülen kararı hangi tipin verdiğiydi, burada ölçülen bir
işleç gövdesinin **kaç kez** koştuğu.

Bu kursun beş dersi boyunca ölçülen her gövde kaynakta bir adla anılabiliyordu: `ad`, bir
sınırlı fonksiyon, `uret`, `statik`/`dinamik`, `eq`. İşleç aşırı yüklemede bu adlandırma
kayboluyor — kaynakta yalnız `+` görünüyor, `add` sözcüğü hiçbir yerde geçmiyor. Bu son
ders, kursun ölçü ekseninin en görünmez uygulamasını taşıyor: bir gövdenin kaç kez koştuğunu
saymak için, önce o gövdeyi çağıran satırı kaynakta **tanımak** gerekiyor ve işleçlerde bu
tanıma adım kaynağın kendisinde değil, dilin sözdizimi kuralında.

## İşleç Bir Trait Çağrısıdır

Rust'ta `+` işleci sabit bir davranış değil, `std::ops::Add` trait'inin bir çağrısı. Bir tip
`+` ile toplanabilir olsun istiyorsa, `Add`i gerçekleştirmesi gerekiyor; gerçekleştirmezse
`+` derlenmez. `a + b` yazımı, derleyici tarafından `Add::add(a, b)`e **açılıyor** — kaynakta
görünen kısayol, arkasında sıradan bir yöntem çağrısı taşıyor.

Bu açılma, önceki dersteki türetmeyle aynı kategoride değil. Türetilmiş bir gövde kaynakta
hiç yazılmıyordu; `add` gövdesi burada tamamen yazılı, `impl Add for Uzunluk` bloğunun
içinde satır satır duruyor. Görünmeyen şey gövde değil, gövdeyi **çağıran** satır — `+`
işareti bir çağrı taşıdığını söylemiyor, yalnız iki değeri yan yana koyuyor. Bu, temel
tamsayı ve kayan noktalı tipler için de aynı: `3 + 4` yazıldığında bile, arka planda aynı
kalıp işliyor, yalnız `i32` gibi ilkel tipler için bu çağrı derleyicinin kendi yerleşik
kurallarıyla, standart kitaplıktaki `Add` gerçekleştirimi üzerinden çözülüyor. `Uzunluk`
gibi kullanıcı tanımlı bir tip için aynı yolu açmak, tam olarak `Add`i gerçekleştirmek
anlamına geliyor.

```rust
// kere.rs — kesit: say/kere defteri, Uzunluk ve Add gerceklestirimi.

use std::cell::RefCell;
use std::collections::BTreeMap;
use std::ops::Add;
use std::rc::Rc;

pub type Defter = Rc<RefCell<BTreeMap<String, u32>>>;

pub fn say(defter: &Defter, ad: &str) {
    *defter.borrow_mut().entry(ad.to_string()).or_insert(0) += 1;
}

pub fn kere(defter: &Defter, ad: &str) -> u32 {
    *defter.borrow().get(ad).unwrap_or(&0)
}

#[derive(Clone)]
pub struct Uzunluk {
    pub deger: i32,
    pub defter: Defter,
}

impl Add for Uzunluk {
    type Output = Uzunluk;
    fn add(self, oteki: Uzunluk) -> Uzunluk {
        say(&self.defter, "islec-govdesi");
        Uzunluk {
            deger: self.deger + oteki.deger,
            defter: Rc::clone(&self.defter),
        }
    }
}
```

`impl Add for Uzunluk` bloğu, önceki derste tanıdık bir yazımı taşıyor: `type Output =
Uzunluk;` satırı, İlişkili Tipler dersinde ele alınan ilişkili tip — `Add`in kendisi, toplamın
sonuç tipini kendi içinde bir tip olarak taşıyor. Bu ders `Output`a değil, `add` gövdesinin
kaç kez çağrıldığına bakıyor.

`add` yönteminin imzası da kendi başına bir gözlem taşıyor: `fn add(self, oteki: Uzunluk) ->
Uzunluk`. Parametre `self`in kendisi (`&self` değil) alınıyor — toplama işlemi iki `Uzunluk`
değerini **tüketiyor**, ödünç almıyor. Bu, Sahiplik ve Bellek Modeli kursunun sahiplik ve
taşıma dersinde kurulan kuralın burada tekrar karşımıza çıkması: `a + b` yazıldığında hem
`a` hem `b` bu ifadeden sonra kullanılamaz hale geliyor, çünkü ikisi de `add`in içine
taşındı. Yukarıdaki `a.clone() + b` yazımında `a`nın önce çoğaltılmasının nedeni tam bu —
`a` ikinci toplamda (`toplam + a`) tekrar kullanılacağı için, ilk toplamda tüketilmemesi
gerekiyor.

## Üç Terim, İki Çağrı

```rust
// islec.rs — bir islecin her kullanimi bir cagridir; uc terimli toplam iki kez cagirir.
mod kere;
use kere::{kere, Defter, Uzunluk};
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::rc::Rc;

fn olustur(defter: &Defter, deger: i32) -> Uzunluk {
    Uzunluk { deger, defter: Rc::clone(defter) }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(BTreeMap::new()));
    let a = olustur(&defter, 3);
    let b = olustur(&defter, 4);

    // Uc terim, iki '+' cagrisi: (a.clone() + b) + a
    let toplam = a.clone() + b;
    let toplam = toplam + a;
    println!(
        "uc-terim-toplam={} islec-govdesi={}",
        toplam.deger,
        kere(&defter, "islec-govdesi")
    );

    // Bes terim, dort '+' cagrisi - ayni ilkeyi ayri bir anahtarla dogruluyor.
    let defter2: Defter = Rc::new(RefCell::new(BTreeMap::new()));
    let bes: Vec<Uzunluk> = (1..=5).map(|d| olustur(&defter2, d)).collect();
    let mut uzun_toplam = bes[0].clone();
    for terim in bes.into_iter().skip(1) {
        uzun_toplam = uzun_toplam + terim;
    }
    println!(
        "bes-terim-toplam={} islec-govdesi={}",
        uzun_toplam.deger,
        kere(&defter2, "islec-govdesi")
    );
}
```

```
uc-terim-toplam=10 islec-govdesi=2
bes-terim-toplam=15 islec-govdesi=4
```

**TR12.** İlk ölçüm üç terimi ((`a`nın bir kopyası, `b`, `a`nın kendisi) topluyor ve
`islec-govdesi` iki kez koştu. Kaynakta `+` işareti de iki kez göründü — `a.clone() + b` ve
sonucun `a` ile toplanması — ve bu görünüm gövdenin kaç kez çağrıldığıyla birebir örtüşüyor. Bu
satır **her seferinde** sınıfına giriyor: işlecin her kullanımı, kaçınılmaz biçimde bir çağrıya
karşılık geliyor. İkinci ölçüm aynı ilkeyi ayrı bir defterle doğruluyor: beş terim toplanırken
kaynakta bir kez yazılan `+` dört kez koştu. İki ölçüm birlikte genel kuralı gösteriyor: **n
terimli bir toplamda işleç gövdesi n eksi bir kez koşar** — ilk terim hiçbir çağrıya ihtiyaç
duymadan zaten elde var, geri kalan her terim bir çağrı gerektiriyor.

Bu kural, toplamanın kendi yapısından geliyor: iki terim toplamak tek bir çağrı, üçüncü
terimi eklemek ikinci bir çağrı, dördüncüyü eklemek üçüncü bir çağrı. Beş terimli döngüde bu
birikim `bes[0]`den başlıyor — henüz hiçbir toplama yapılmadığı için sıfır çağrı — ve her
yeni terim bir çağrı ekleyerek dört çağrıda tamamlanıyor. Kaynaktaki döngü gövdesi tek bir
satır (`uzun_toplam = uzun_toplam + terim;`), ama bu satırın **kaç kez** yazıldığı değil,
**kaç kez çalıştığı** önemli — kaynakta bir kez yazılan bir satır, döngü aracılığıyla
kendini dört kez tekrar ediyor. Bu, İşleç Aşırı Yükleme dersinin taşıdığı ek bir gözlem: bir
çağrının kaynakta kaç kez **yazıldığı** ile koşumda kaç kez **çalıştığı** farklı sayılar
olabilir ve döngü bu ikisini ayrıştıran en yaygın araç.

Nesneye Dayalı Java kursu işleç aşırı yüklemenin **kararı hangi tipin verdiğini** ölçmüştü —
bir işlecin hangi gerçekleştirimin çağrılacağını işlenen değerlerin bildirilen tipinin mi
çalışma zamanı tipinin mi belirlediğini. Bu kurs o soruyu tekrar sormuyor; burada ölçülen,
zaten belirlenmiş bir gerçekleştirimin gövdesinin **kaç kez** koştuğu. Rust'ta bu belirleme
zaten derleme zamanında, `Uzunluk`in somut tipinden okunarak yapılıyor — kararın kendisi bu
dersin konusu değil.

## Sözdizimi Kısayoldur, Çağrı Aynı

`+` yazımının bir kısayol olduğu, `Add::add`i açıkça çağırarak da doğrulanabilir — iki yazım
aynı çağrıya açılıyorsa, ikisinin de koşum defterine bıraktığı iz aynı olmalı.

```rust
// islec-esdeger.rs — '+' yazimi ile Add::add cagrisi ayni sayida kosuyor.
mod kere;
use kere::{kere, Defter, Uzunluk};
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::ops::Add;
use std::rc::Rc;

fn olustur(defter: &Defter, deger: i32) -> Uzunluk {
    Uzunluk { deger, defter: Rc::clone(defter) }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(BTreeMap::new()));
    let a = olustur(&defter, 5);
    let b = olustur(&defter, 6);

    // Iki yazim, ayni cagri: '+' iceren ve Add::add'i acikca cagiran.
    let sozdizimiyle = a.clone() + b.clone();
    let acikca = Add::add(a, b);

    println!("sozdizimiyle={} acikca={}", sozdizimiyle.deger, acikca.deger);
    println!("islec-govdesi={}", kere(&defter, "islec-govdesi"));
}
```

```
sozdizimiyle=11 acikca=11
islec-govdesi=2
```

**TR13.** `a.clone() + b.clone()` bir çağrı, `Add::add(a, b)` bir çağrı — ikisi de aynı
`add` gövdesini tetikliyor ve `islec-govdesi` iki kez koşuyor. Bu, `+` işaretinin
derleyiciye yeni bir davranış eklemediğini, yalnız zaten var olan bir çağrıyı kısaltarak
yazmanın bir yolu olduğunu doğruluyor. `Add::add(a, b)` yazımı, trait'in adını ve yöntemini
açıkça taşıyor; `a + b` aynı çağrıyı taşıyor ama adı gizliyor. İkisi arasında seçim yapmak
koşum sayısını hiç etkilemiyor, yalnız kaynağın **okunabilirliğini** etkiliyor.

`Add` tek başına değil; `std::ops` modülü her ikili işleç için benzer bir trait taşıyor —
çıkarma için `Sub`, çarpma için `Mul`, dizin erişimi için `Index`. Hepsi aynı ilkeye
dayanıyor: bir işaret, bir trait çağrısına açılıyor. Bu ders yalnız `Add`i ölçtü, ama sayım
yöntemi hepsi için aynı kalır: her kullanım bir çağrıdır ve zincirlendiklerinde çağrı
sayısı terim sayısından bir eksik olur.

Bu genelleme bir varsayım değil, `Add` ile aynı kalıbın diğer trait'lerde de tekrarlanmasından
geliyor: `Sub` `sub` adlı, `Mul` `mul` adlı, `Index` `index` adlı tek bir yöntem bildiriyor
ve her biri kendi işaretinin (`-`, `*`, `[]`) arkasına aynı biçimde gizleniyor. Bir tipin
birden fazla işleci aşırı yüklemesi de mümkün — `Uzunluk` isteseydi hem `Add` hem `Sub`
gerçekleştirebilirdi, ikisi de bağımsız `impl` bloklarında dururdu ve biri diğerinin koşum
sayısını etkilemezdi. Bu ders yalnız `Add`e odaklandı çünkü kursun ölçüm çekirdeği zaten onu
taşıyordu; ilke kalan işleçler için de aynı kalıyor.

## Sınırlayıcı Ölçüm

İşleç gövdesi sıradan bir yöntemdir, ama **çağrıldığı yer kaynakta görünmez**. `a.clone() +
b` yazımında `add` sözcüğü hiçbir yerde geçmiyor — çağrı, `+` işaretinin arkasında gizli.
Bir okuyucu kaynağa bakarak "bu ifadede kaç çağrı var" sorusunu, işaretleri sayarak yanıtlar:
her `+` bir çağrıdır. Ama zincir uzadıkça, özellikle bir döngü ya da bir yineleyici zinciri
içinde üretildiğinde, kaynaktaki `+` işaretlerini saymak da yeterli olmayabilir — döngünün
kaç kez çalıştığı da bilinmesi gereken bir bilgidir. Yukarıdaki beş terimli döngüde kaynakta
tek bir `+` yazıyor (`uzun_toplam = uzun_toplam + terim;`), ama bu satır döngü içinde dört
kez çalıştığı için toplam çağrı sayısı dört. Kaynaktaki işaret sayısı ile çalışma zamanındaki
çağrı sayısı burada ayrışıyor: **kaç kez koştuğu ancak sayılarak, ancak koşum defteriyle
bilinebiliyor** — kaynağı okuyarak değil.

Bu, kursun baştan beri sorduğu sorunun son biçimi: kaynakta yazdığın bir gövde kaç kez koştu?
İşleç aşırı yüklemede bu soru en görünmez haliyle karşımıza çıkıyor, çünkü çağrının kendisi
bir ad taşımıyor — yalnız bir işaret. Kurs boyunca ölçülen on altı gövdenin sonuncusu da bu
işaretin arkasında duruyordu.

Bu görünmezlik, kursun ilk dersindeki bir gözlemi tersinden doğruluyor. Rust'ın Tasarım
Hedefleri dersi, `HashSet::insert` ile `Vec::push`in aynı işi (ekleme) yaptığını ama
imzalarına bakarak farklı sınıflara girdiğini göstermişti — sınıf, kaynaktan **okunarak**
belirlenebiliyordu. İşleç aşırı yüklemede ise sınıf (her seferinde) kaynaktan yine
okunabiliyor — `+` her zaman bir çağrıdır — ama çağrı **sayısı** kaynaktan okunamıyor,
çünkü kaynaktaki her `+` işareti bir döngü içindeyse birden fazla kez çalışabiliyor. Kurs
boyunca "sınıf kaynaktan okunur, sayı koşumdan gelir" ayrımı burada en net haliyle
görünüyor.

Bu altı ders, aynı soruyu altı farklı düzenekte sordu. Trait Tanımı ve Gerçekleştirimi,
kaynakta yazılı bir varsayılan gövdenin bir tip için koşup başka bir tip için hiç
koşmadığını gösterdi. Trait Sınırları, o gövdenin etrafına konan bir koşulun koşum sayısına
hiç dokunmadığını gösterdi. İlişkili Tipler, aynı sözleşmenin iki farklı yazımının koşum
sayısını eşit bıraktığını, farkın çağıranın yazdığında olduğunu gösterdi. Nesne Güvenliği ve
Dinamik Gönderim, çağrının derleme zamanında mı koşum zamanında mı çözüldüğünün de sayıyı
değiştirmediğini gösterdi. Türetilen Trait'ler, bir gövdenin kaynakta hiç yazılı olmadan da
koştuğunu, ama bu koşumun sayılamadığını gösterdi. Ve bu ders, yazılı bir gövdenin çağrısının
kaynakta görünmez olabileceğini gösterdi. Altısı birlikte, "kaç kez koştu" sorusunun
kaynaktaki görünürlükten bağımsız bir soru olduğunu ortaya koyuyor: bazen görünen gövde
koşmuyor, bazen görünmeyen bir çağrı koşuyor.

## Özet

- Bir işlecin (`+` gibi) kullanımı, standart kitaplıktaki bir trait'in (`Add`) yöntem
  çağrısına karşılık gelir; kaynakta görünen kısayol arkasında sıradan bir çağrı taşır.
- İşleç gövdesi (`islec-govdesi`) her seferinde sınıfına girer: üç terimli bir toplamda iki
  kez, beş terimli bir toplamda dört kez koşar — çağrı sayısı her zaman terim sayısından bir
  eksiktir.
- İşlecin sözdizimsel kısalığı çağrı sayısını değiştirmez; `Uzunluk::add`i elle çağırmakla
  `+` yazmak aynı sayıda çalışır.
- Çağrı yeri kaynakta görünmediği için (yalnız bir işaret görünür), kaç kez koştuğu
  kaynağı okuyarak değil, ancak koşum defteriyle sayılarak bilinebilir.

Bu genel kural — n terim, n eksi bir çağrı — yalnız `Add` için değil, ikili işleçleri
zincirleyen her yazım için geçerli. Zincirin uzunluğu kaynakta bir kez yazılıp bir döngüyle
tekrarlanıyorsa (yukarıdaki beş terimli örnekte olduğu gibi), çağrı sayısını önceden
bilmenin tek yolu döngünün kaç kez çalışacağını bilmek; kaynaktaki işleç işaretlerini saymak
tek başına yeterli değil. Bu, kursun başından beri sürdürdüğü ayrımın son örneği: kaynak
**neyin** koşacağını söylüyor, koşum **kaç kez** koştuğunu söylüyor ve ikisi aynı bilgiyi
taşımıyor.

## Sonraki Adım

Bu kurs, bir gövdenin ne zaman koştuğunu — her seferinde, yalnız gerektiğinde, hiç — sorarak
trait'leri, sınırları, ilişkili tipleri, gönderim biçimlerini, türetilmiş gövdeleri ve işleç
çağrılarını ölçtü. Sıradaki konu aynı soruyu bir gövdenin **başarısız olabileceği** yerlere
taşıyor: bir değerin yokluğu tipte nasıl ifade edilir ve o yokluğu karşılayan bir gövde
her zaman mı, yoksa yalnız gerektiğinde mi koşar?
