Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 2 — Konu 7: Tip Çıkarımı (Type Inference) ve Açık Tip Belirtme

3 dk okuma #dart

Tip Çıkarımı Nedir?

Önceki derslerde var kullaniciAdi = "Ahmet"; gibi örnekler yazdık ama hiç String yazmadık — buna rağmen Dart, kullaniciAdi'nin bir String olduğunu biliyor. Bu, tip çıkarımı (type inference) sayesinde oluyor: derleyici, verdiğin ilk değere bakarak tipi kendisi belirliyor.

dart
void main() {
  var isim = "Elif";     // Dart bunun String olduğunu anlar
  var yas = 30;           // Dart bunun int olduğunu anlar
  var boy = 1.65;         // Dart bunun double olduğunu anlar
  var aktif = true;       // Dart bunun bool olduğunu anlar
}

Bunu doğrulamak istersen, VS Code'da bir değişkenin üzerine fare ile gelirsen (hover), Dart eklentisi sana o değişkenin çıkarılmış tipini gösterir — kod içinde yazılı olmasa bile.

Açık (Explicit) Tip Belirtme

var yerine, tipi doğrudan sen de yazabilirsin:

dart
void main() {
  String isim = "Elif";
  int yas = 30;
  double boy = 1.65;
  bool aktif = true;
}

Bu iki yaklaşım (tip çıkarımı vs açık belirtme) fonksiyonel olarak tamamen aynı sonucu verir — ikisinde de değişken statik olarak tiplendirilmiştir, ikisinde de derleme zamanında tip kontrolü yapılır. Fark sadece sözdizimseldir (syntactic), yani nasıl yazdığınla ilgilidir.

Peki Hangisini Ne Zaman Kullanmalı?

Bu, Dart topluluğunda biraz tartışmalı bir stil konusudur, ama genel kabul gören pratikler şunlar:

var kullan, eğer:

  • Değişkenin tipi, atadığın değerden zaten apaçık belliyse:
    dart
    var kullaniciAdi = "mehmet123"; // String olduğu zaten çok açık

Açık tip belirt, eğer:

  • Tip, ilk bakışta belli değilse veya kodun okunabilirliğini artıracaksa:
    dart
    double hesaplaOrtalama(List<int> sayilar) {
    double toplam = 0; // burada "double" yazmak, "bu bir tam sayı değil" diye netlik katıyor
    for (var s in sayilar) {
      toplam += s;
    }
    return toplam / sayilar.length;
    }
  • Bir fonksiyonun parametrelerinde ve dönüş tipinde her zaman açık tip belirtilir (bu zorunludur, var fonksiyon imzasında kullanılmaz — bunu Bölüm 5'te fonksiyonlar konusunda detaylı göreceğiz).

var ≠ dynamic — Kritik Bir Ayrım

Yeni başlayanların en çok karıştırdığı nokta budur. var ile tanımlanan bir değişken statik olarak tiplendirilmiştir — tip, derleme zamanında sabitlenir ve bir daha değişmez:

dart
void main() {
  var mesaj = "Merhaba";
  mesaj = 42; // ❌ HATA! mesaj zaten String olarak sabitlendi
}

Bunu bir sonraki konuda (dynamic ve Object) çok daha net göreceğiz — orada gerçekten "tipi çalışma zamanında değişebilen" bir değişken türünü işleyeceğiz. Şimdilik şunu bil: var, "tipsiz değişken" demek değildir — "tipi otomatik belirlenen değişken" demektir.

Tip Çıkarımı Fonksiyonlarda da Çalışır

dart
selamVer(isim) {
  return "Merhaba, $isim!";
}

Yukarıdaki gibi bir fonksiyon yazarsan, Dart parametrenin ve dönüş değerinin tipini dynamic olarak kabul eder (bu iyi bir pratik değildir — bir sonraki derste neden kaçınılması gerektiğini göreceğiz). Doğrusu:

dart
String selamVer(String isim) {
  return "Merhaba, $isim!";
}

Fonksiyonlarda tip çıkarımı dönüş tipi için de kullanılabilir (=> ile yazılan arrow function'larda derleyici çıkarım yapabilir), ama en iyi pratik, fonksiyon imzalarında tipleri her zaman açıkça yazmaktır — çünkü bir fonksiyonu çağıran başka bir geliştirici (ya da gelecekteki sen), parametrenin ne beklediğini kod içine bakmadan, sadece imzayı okuyarak anlayabilmeli.

Koleksiyonlarda Tip Çıkarımı — Küçük Bir Önizleme

Bölüm 4'te koleksiyonları detaylı işleyeceğiz ama tip çıkarımının orada da çalıştığını görmen faydalı:

dart
void main() {
  var sayilar = [1, 2, 3]; // Dart bunun List<int> olduğunu anlar
  var isimler = ["Ali", "Veli"]; // List<String>
}

Yine burada var kullanmak yaygın bir pratiktir çünkü liste içeriğinden tip zaten belli oluyor.

Bir Kural Daha: Tutarlılık

Bir projede/takımda hangi yaklaşım seçilirse seçilsin (bazıları her yerde açık tip yazmayı, bazıları mümkün olduğunca var kullanmayı tercih eder), önemli olan tutarlı olmaktır. dart analyze aracı (Bölüm 13'te detaylandıracağız), projene özel lint kuralları tanımlayarak bu tutarlılığı zorunlu kılmana bile izin verir.

Küçük Bir Karşılaştırma Örneği

dart
// Yaklaşım 1: Tip çıkarımı (var)
void main() {
  var toplamPuan = 0;
  var ogrenciSayisi = 25;
  var ortalama = toplamPuan / ogrenciSayisi;
  print(ortalama);
}

// Yaklaşım 2: Açık tip belirtme
void main() {
  int toplamPuan = 0;
  int ogrenciSayisi = 25;
  double ortalama = toplamPuan / ogrenciSayisi;
  print(ortalama);
}

İki kod da tamamen aynı şekilde çalışır, aynı hataları yakalar (örneğin toplamPuan'a bir String atamaya çalışırsan ikisi de hata verir). Fark tamamen okunabilirlik tercihi.


🎯 Bu Dersten Çıkarılması Gerekenler

  • Tip çıkarımı, var ile tanımlanan değişkenin tipini ilk değerden otomatik belirler.
  • var ile açık tip belirtme fonksiyonel olarak aynıdır, sadece sözdizimsel bir tercih.
  • var, dynamic değildir — tip bir kere belirlenir ve sabitlenir.
  • Fonksiyon parametrelerinde ve dönüş tiplerinde açık tip belirtmek en iyi pratiktir.
  • Önemli olan, seçtiğin yaklaşımda tutarlı olmak.

📝 Ödevler

  • [ ] Aynı 4 değişkeni (isim, yaş, boy, öğrenci mi) bir kere var ile bir kere açık tip belirterek iki ayrı main() fonksiyonunda tanımla, ikisinin de aynı şekilde çalıştığını doğrula.
  • [ ] var ile tanımladığın bir değişkene, tanımlandığı tipten farklı bir değer atamayı dene (örn. var x = 5; x = "beş";), hatayı oku ve yorumla.
  • [ ] VS Code'da bir var değişkeninin üzerine fare ile gelip Dart eklentisinin gösterdiği çıkarılmış tipi kontrol et.
  • [ ] Parametre ve dönüş tipi açıkça belirtilmiş bir fonksiyon yaz (örn. iki sayının ortalamasını double olarak döndüren), fonksiyonları henüz detaylı işlemedik ama bu basit örneği dene.

Sıradaki konu: Bölüm 2 — Konu 8: dynamic ve Object — Ne Zaman Kullanılır, Ne Zaman Kaçınılır