↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 5 — Konu 22: Varsayılan Parametre Değerleri (Derinlemesine)

2 dk okuma #dart
Dizi · 21/64 Dart Türkçe Tutorial
  1. Bölüm 1 — Konu 1: Dart Nedir, Nerede Kullanılır, Neden Flutter Bu Dili Seçti
  2. Bölüm 1 — Konu 2: Ortam Kurulumu (Dart SDK, DartPad, Terminal ile Çalıştırma)
  3. Bölüm 1 — Konu 3: İlk Program (`main()`, `print()`, Dosya Yapısı)
  4. Bölüm 1 — Konu 4: Yorum Satırları, Temel Sözdizimi Kuralları
  5. Bölüm 2 — Konu 5: Değişken Tanımlama — `var`, `final`, `const` Farkı
  6. Bölüm 2 — Konu 6: Temel Tipler — `int`, `double`, `String`, `bool`
  7. Bölüm 2 — Konu 7: Tip Çıkarımı (Type Inference) ve Açık Tip Belirtme
  8. Bölüm 2 — Konu 8: `dynamic` ve `Object` — Ne Zaman Kullanılır, Ne Zaman Kaçınılır
  9. Bölüm 2 — Konu 9: Null Safety Temelleri (`?`, `!`, `late`'e Giriş)
  10. Bölüm 3 — Konu 10: Aritmetik, Atama, Karşılaştırma, Mantıksal Operatörler
  11. Bölüm 3 — Konu 11: `if / else if / else`
  12. Bölüm 3 — Konu 12: `switch` / `switch expression` (Modern Dart)
  13. Bölüm 3 — Konu 13: Ternary Operatör, `??`, `??=`, `?.`
  14. Bölüm 3 — Konu 14: `for`, `while`, `do-while` Döngüleri
  15. Bölüm 4 — Konu 16: `List` — Oluşturma, Erişim, Temel Metodlar
  16. Bölüm 4 — Konu 17: `Set` — Benzersiz Eleman Mantığı
  17. Bölüm 4 — Konu 18: `Map` — Key-Value Yapılar
  18. Bölüm 4 — Konu 19: Koleksiyon Üzerinde `for-in`, `forEach`
  19. Bölüm 4 — Konu 20: Spread Operatörü (`...`, `...?`) ve Collection If/For
  20. Bölüm 5 — Konu 21: Fonksiyon Tanımlama, Parametreler (Positional, Named, Optional)
  21. Bölüm 5 — Konu 22: Varsayılan Parametre Değerleri (Derinlemesine)
  22. Bölüm 5 — Konu 23: Arrow Function (`=>`) Sözdizimi
  23. Bölüm 5 — Konu 24: Fonksiyonlar Birinci Sınıf Vatandaş — Değişkene Atama, Parametre Olarak Geçme
  24. Bölüm 5 — Konu 25: Anonim Fonksiyonlar ve Closure Kavramı (Derinlemesine)
  25. Bölüm 5 — Konu 26: Recursion (Özyineleme)
  26. Bölüm 6 — Konu 27: Class Tanımlama, Constructor (Varsayılan, Named, Factory)
  27. Bölüm 6 — Konu 28: Alanlar (Fields), Metodlar, `this` Kullanımı (Derinlemesine)
  28. Bölüm 6 — Konu 29: Initializer List, Constructor Kısayolları (Derinlemesine)
  29. Bölüm 6 — Konu 30: Getter / Setter
  30. Bölüm 6 — Konu 31: Statik Üyeler (`static`)
  31. Bölüm 7 — Konu 32: Kalıtım (`extends`), `super` Kullanımı
  32. Bölüm 7 — Konu 33: Metod Override Etme, `@override`
  33. Bölüm 7 — Konu 34: Soyut Sınıflar (`abstract class`)
  34. Bölüm 7 — Konu 35: Interface Mantığı (`implements`)
  35. Bölüm 7 — Konu 36: Mixin (`with`)
  36. Bölüm 7 — Konu 37: `enum` — Basit ve Gelişmiş (Metotlu Enum'lar)
  37. Bölüm 8 — Konu 38: `try / catch / finally`, `throw`
  38. Bölüm 8 — Konu 39: Özel Exception Sınıfları Yazma
  39. Bölüm 8 — Konu 40: Sound Null Safety Derinlemesine — `late`, `required`, Non-Nullable Varsayılan Davranış
  40. Bölüm 8 — Konu 41: `assert` ile Geliştirme Zamanı Kontrolleri
  41. Bölüm 9 — Konu 42: Generic Sınıflar ve Fonksiyonlar
  42. Bölüm 9 — Konu 43: Generic Sınırlamalar (`<T extends ...>`)
  43. Bölüm 9 — Konu 44: Dart'ın Built-in Generic Koleksiyonları Nasıl Çalışır
  44. Bölüm 10 — Konu 45: `Future` Kavramı, `async`/`await`
  45. Bölüm 10 — Konu 46: `Future.then`, Hata Yönetimi (`catchError`)
  46. Bölüm 10 — Konu 47: `Stream` Temelleri, `async*`, `yield`
  47. Bölüm 10 — Konu 48: `StreamController`, Broadcast Stream
  48. Bölüm 11 — Konu 49: `map`, `where`, `reduce`, `fold`
  49. Bölüm 11 — Konu 50: `sort`, Custom Comparator ile Sıralama
  50. Bölüm 11 — Konu 51: Iterable Kavramı Derinlemesine (Lazy Evaluation)
  51. Bölüm 11 — Konu 52: Cascade Notasyonu (`..`)
  52. Bölüm 12 — Konu 53: `pubspec.yaml`, pub.dev'den Paket Ekleme
  53. Bölüm 12 — Konu 54: Kütüphane Oluşturma, `import`/`export`, `part`/`part of`
  54. Bölüm 12 — Konu 55: Dart'ta Test Yazımı (`test` Paketi, Unit Test Mantığı)
  55. Bölüm 12 — Konu 56: Extension Methods
  56. Bölüm 12 — Konu 57: Dart'ın Derleme Modelleri (JIT vs AOT) ve Bunun Flutter'a Etkisi
  57. Bölüm 13 — Konu 59: Dart 3 Pattern Matching — Records, Destructuring, Sealed Classes, Exhaustive Switch
  58. Bölüm 13 — Konu 60: `Never` Tipi, `covariant` ve Generic Variance Detayları
  59. Bölüm 13 — Konu 61: Event Loop Derinlemesine — Microtask Queue vs Event Queue
  60. Bölüm 13 — Konu 62: Memory Model & Performans — Garbage Collection, `const` Nesnelerin Bellek Avantajı
  61. Bölüm 13 — Konu 63: Isolate'ler Arası Mesajlaşmanın Maliyeti ve `compute()`'un İç İşleyişi
  62. Bölüm 13 — Konu 64: FFI (Foreign Function Interface) — C Koduna Erişim
  63. Bölüm 13 — Konu 65: Sunucu Tarafında Dart — `dart:io`, `shelf` Paketiyle Basit Bir Backend/CLI Aracı Yazma
  64. Bölüm 13 — Konu 66: Derleyici & Analiz Araçları — `dart analyze`, Custom Lint Kuralları, `build_runner` Mimarisi
Dizinin sayfası →
İçindekiler 7 başlık
  1. Temel Kullanım — Hatırlatma
  2. Kritik Kural: Varsayılan Değer Derleme Zamanında Sabit Olmalı
  3. Koleksiyon Varsayılan Değerleri — Dikkat Edilmesi Gereken Bir Tuzak
  4. Basit Tiplerle Varsayılan Değerler — Sorunsuz
  5. null Varsayılan Değeri — Örtük mü, Açık mı?
  6. 🎯 Bu Dersten Çıkarılması Gerekenler
  7. 📝 Ödevler

Önceki derste varsayılan değerlere kısaca değinmiştik ([int yas = 18] gibi). Bu derste bunu derinlemesine işleyip, dikkat edilmesi gereken ince detayları göreceğiz.

Temel Kullanım — Hatırlatma

dart
void selamVer(String isim, [String selam = "Merhaba"]) {
  print("$selam, $isim!");
}

void main() {
  selamVer("Ahmet");           // Merhaba, Ahmet!
  selamVer("Ayşe", "Selam");   // Selam, Ayşe!
}

Named parametrelerde de aynı mantık geçerli:

dart
void selamVer2({String isim = "Misafir", String selam = "Merhaba"}) {
  print("$selam, $isim!");
}

void main() {
  selamVer2(); // Merhaba, Misafir!
  selamVer2(isim: "Can"); // Merhaba, Can!
}

Kritik Kural: Varsayılan Değer Derleme Zamanında Sabit Olmalı

Bu, Bölüm 2'de öğrendiğimiz const kavramıyla doğrudan ilişkilidir. Bir parametrenin varsayılan değeri, derleme zamanında bilinen bir sabit (compile-time constant) olmak zorundadır:

dart
void logMesaj(String mesaj, [DateTime? zaman]) {
  zaman ??= DateTime.now(); // ✅ doğrusu — fonksiyon GÖVDESİ içinde atama
  print("[$zaman] $mesaj");
}

Ama şunu yapamazsın:

dart
void logMesajYanlis(String mesaj, [DateTime zaman = DateTime.now()]) {
  // ❌ HATA! DateTime.now() derleme zamanında bilinen bir sabit değil
  print("[$zaman] $mesaj");
}

Neden? Çünkü varsayılan değerler, Dart derleyicisi tarafından fonksiyonun imzasının bir parçası olarak "gömülür" — bu değerin, programın her çalıştırılışında (yani derleme anında) aynı olması gerekir. DateTime.now() her çalıştırıldığında farklı bir sonuç verdiği için (runtime'da belirlenir), bu kural ihlal edilmiş olur.

Doğru pratik: Runtime'da belirlenmesi gereken bir "varsayılan" değer istiyorsan, parametreyi null yapıp gövde içinde ??= ile ata (yukarıdaki logMesaj örneğinde gördüğün gibi).

Koleksiyon Varsayılan Değerleri — Dikkat Edilmesi Gereken Bir Tuzak

dart
void listeyeEkle(String eleman, [List<String> hedefListe = const []]) {
  // hedefListe.add(eleman); // ❌ HATA! const liste değiştirilemez
  print(hedefListe);
}

Varsayılan bir liste/map/set kullanmak istediğinde, bunun const olması gerekir (çünkü yukarıdaki kuralı hatırla — derleme zamanı sabiti olmalı). Ama const bir koleksiyon, Bölüm 4'te gördüğümüz gibi değiştirilemez. Bu yüzden varsayılan olarak boş bir liste veren ve o listeyi değiştirmek isteyen bir fonksiyon yazarsan, dikkatli olmalısın:

dart
List<String> listeyeEkle(String eleman, [List<String>? hedefListe]) {
  hedefListe ??= []; // her çağrıda TAZE bir liste oluşturulur
  hedefListe.add(eleman);
  return hedefListe;
}

void main() {
  var sonuc1 = listeyeEkle("Elma");
  print(sonuc1); // [Elma]

  var sonuc2 = listeyeEkle("Armut");
  print(sonuc2); // [Armut] — sonuc1'i etkilemedi, çünkü her çağrıda yeni liste
}

Bu, birçok dilde (özellikle Python'da) yaygın bir hata kaynağıdır — "mutable default argument" tuzağı. Dart, const zorunluluğuyla bu tuzağın bir kısmını baştan engeller, ama yine de nullable + ??= kalıbını bilmek önemlidir.

Basit Tiplerle Varsayılan Değerler — Sorunsuz

dart
void ayarlaSes(int seviye, [bool sessiz = false, String mod = "normal"]) {
  print("Ses: $seviye, Sessiz: $sessiz, Mod: $mod");
}

void main() {
  ayarlaSes(50);
  ayarlaSes(80, true, "gece");
}

int, bool, String gibi ilkel tiplerin sabit değerleri (0, false, "normal" gibi) zaten doğal olarak derleme zamanı sabitleridir, bu yüzden bunlarla varsayılan değer kullanmak hiçbir sorun çıkarmaz.

null Varsayılan Değeri — Örtük mü, Açık mı?

Eğer bir optional parametreye hiç varsayılan değer vermezsen, Dart otomatik olarak null'ı varsayılan yapar (parametre nullable ise):

dart
void mesajYaz(String metin, [String? ekBilgi]) {
  print(metin);
  if (ekBilgi != null) print(ekBilgi);
}

void main() {
  mesajYaz("Merhaba"); // ekBilgi otomatik olarak null
}

Bu, [String? ekBilgi = null] yazmakla aynı anlama gelir — ama = null kısmını açıkça yazmak gereksizdir ve önerilmez (Dart bunu zaten varsayılan yapar, yazmak fazladan gürültü yaratır).


🎯 Bu Dersten Çıkarılması Gerekenler

  • Varsayılan değerler derleme zamanında bilinen sabitler olmalı — DateTime.now() gibi runtime değerleri kullanılamaz.
  • Runtime'da belirlenen bir "varsayılan" istiyorsan, parametreyi nullable yap ve gövde içinde ??= kullan.
  • Varsayılan koleksiyonlar const olmak zorundadır, bu yüzden değiştirilemez — mutable bir varsayılan istiyorsan nullable + ??= kalıbını kullan.
  • Basit tipler (int, bool, String) için varsayılan değer kullanımı sorunsuzdur.
  • Nullable bir optional parametreye varsayılan değer vermezsen, otomatik olarak null olur — bunu açıkça yazmaya gerek yoktur.

📝 Ödevler

  • [ ] DateTime.now()'ı doğrudan varsayılan değer olarak vermeyi dene, derleyicinin verdiği hatayı oku; sonra nullable parametre + ??= ile doğru şekilde düzelt.
  • [ ] Varsayılan olarak boş bir liste alan ve o listeye eleman ekleyen bir fonksiyon yaz — nullable + ??= kalıbıyla, her çağrıda "taze" bir liste oluştuğunu iki ayrı çağrıyla kanıtla.
  • [ ] İki basit tip (örn. int ve bool) için varsayılan değerli, üç parametreli bir fonksiyon yaz; parametreleri hiç vermeden, kısmen vererek ve tam vererek üç farklı şekilde çağır.
  • [ ] Named bir parametrede = null yazmanın gereksiz olduğunu gösteren (yazmadan da aynı davranışın oluştuğu) bir karşılaştırma örneği yap.

Sıradaki konu: Bölüm 5 — Konu 23: Arrow Function (=>) Sözdizimi