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