Bölüm 8 — Konu 38: `try / catch / finally`, `throw`
Dizi · 37/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 11 başlık
- Exception (İstisna) Nedir?
- try / catch — İstisnayı Yakalama
- catch ile Hata Tipini Belirtme — on
- on ve catch'i Birlikte Kullanma — Hem Tip Hem Detay
- finally — Her Durumda Çalışan Blok
- throw — Kendi Hatanı Fırlatmak
- throw ile Herhangi Bir Değer Fırlatılabilir mi?
- Hatayı Yakalayıp Tekrar Fırlatmak — rethrow
- Stack Trace — Hatanın Nerede Oluştuğunu Görme
- 🎯 Bu Dersten Çıkarılması Gerekenler
- 📝 Ödevler
Bölüm 8'e hoş geldin. Bu bölümde, programın beklenmedik durumlarla (hatalarla) nasıl güvenli bir şekilde başa çıkacağını öğreneceğiz.
Exception (İstisna) Nedir?
Bir program çalışırken, beklenmedik bir durumla karşılaşabilir — örneğin sıfıra bölme, geçersiz bir veri formatı, var olmayan bir dosyaya erişim gibi. Dart, bu tür durumları exception (istisna) olarak "fırlatır" (throw eder). Eğer bu istisna yakalanmazsa, program çöker.
void main() {
int a = 10;
int b = 0;
print(a ~/ b); // ❌ RUNTIME HATASI! IntegerDivisionByZeroException
print("Bu satır hiç çalışmaz");
}Bu programı çalıştırdığında, ~/ 0 satırında program çöker ve bir sonraki satır hiç çalışmaz.
try / catch — İstisnayı Yakalama
void main() {
int a = 10;
int b = 0;
try {
print(a ~/ b);
} catch (e) {
print("Bir hata oluştu: $e");
}
print("Program devam ediyor!");
}Çıktı:
Bir hata oluştu: IntegerDivisionByZeroException
Program devam ediyor!Yapıyı parçalayalım:
try { ... }— hata verebilecek kodu buraya yazarsın.catch (e) { ... }— eğertrybloğunda bir hata oluşursa, buradaki kod çalışır;e, oluşan hatayı temsil eden bir değişkendir.
Bu sayede, hata oluşsa bile program çökmez, akış catch bloğuna geçer ve devam eder.
catch ile Hata Tipini Belirtme — on
void main() {
try {
int a = 10;
int b = 0;
print(a ~/ b);
} on IntegerDivisionByZeroException {
print("Sıfıra bölme hatası!");
} catch (e) {
print("Başka bir hata: $e");
}
}on TipAdı, sadece belirli bir tip hatayı yakalamak istediğinde kullanılır. Bu, farklı hata türlerine farklı şekilde tepki vermeni sağlar:
void main() {
try {
int sayi = int.parse("merhaba"); // FormatException fırlatır
} on FormatException {
print("Geçersiz sayı formatı!");
} on IntegerDivisionByZeroException {
print("Sıfıra bölme hatası!");
} catch (e) {
print("Bilinmeyen bir hata: $e");
}
}Dart, try bloğunda hata oluştuğunda, on bloklarını yukarıdan aşağıya sırayla kontrol eder ve hatanın tipine uyan ilk bloğu çalıştırır. Hiçbiri uymazsa, genel catch bloğu (varsa) devreye girer — bu, Bölüm 3'te öğrendiğimiz switch/else if mantığına benzer bir sıralı kontrol.
on ve catch'i Birlikte Kullanma — Hem Tip Hem Detay
void main() {
try {
int sayi = int.parse("abc");
} on FormatException catch (e) {
print("Format hatası: ${e.message}");
}
}on FormatException catch (e), hem belirli bir tipi yakalıyor hem de o hatanın detaylarına (e.message gibi) erişim sağlıyor. FormatException'ın kendi özel alanları vardır (message gibi), bunlara e üzerinden ulaşabilirsin.
finally — Her Durumda Çalışan Blok
void main() {
try {
print("Deneme yapılıyor");
int sonuc = 10 ~/ 0;
} catch (e) {
print("Hata yakalandı: $e");
} finally {
print("Bu her durumda çalışır — hata olsa da olmasa da!");
}
}Çıktı:
Deneme yapılıyor
Hata yakalandı: IntegerDivisionByZeroException
Bu her durumda çalışır — hata olsa da olmasa da!finally bloğu, hata olsun ya da olmasın, her zaman çalışır. Bu, genelde temizlik işlemleri için kullanılır — örneğin bir dosyayı kapatmak, bir bağlantıyı sonlandırmak gibi işlemler, hata oluşsa bile mutlaka yapılması gereken işlerdir.
void main() {
try {
print("İşlem başarılı");
} finally {
print("Temizlik yapılıyor");
}
// catch bloğu olmadan da finally kullanılabilir
}throw — Kendi Hatanı Fırlatmak
Şimdiye kadar Dart'ın kendiliğinden fırlattığı hataları (IntegerDivisionByZeroException, FormatException) gördük. Kendi kodunda da, bir durumun "hata" olduğuna karar verip bunu bilerek fırlatabilirsin:
void yasKontrolEt(int yas) {
if (yas < 0) {
throw Exception("Yaş negatif olamaz");
}
print("Yaş: $yas");
}
void main() {
try {
yasKontrolEt(-5);
} catch (e) {
print("Hata yakalandı: $e");
}
}Çıktı:
Hata yakalandı: Exception: Yaş negatif olamazthrow, o anki fonksiyonun çalışmasını anında durdurur ve belirtilen hatayı "fırlatır" — bu hata, en yakın uygun try/catch bloğu tarafından yakalanana kadar, çağıran fonksiyonlar zinciri boyunca yukarı doğru "yayılır" (propagate olur).
throw ile Herhangi Bir Değer Fırlatılabilir mi?
void main() {
try {
throw "Basit bir string hata"; // teknik olarak çalışır
} catch (e) {
print(e); // Basit bir string hata
}
}Teknik olarak throw, herhangi bir nesneyi fırlatabilir (sadece Exception sınıfından türeyen bir şey olması zorunlu değildir). Ama bu önerilmez — Dart'ın standart pratiği, Exception veya Error sınıflarından türeyen (ya da bunları doğrudan kullanan) nesneleri fırlatmaktır, çünkü bunlar daha fazla bilgi taşır ve on ExceptionTipi ile daha kolay yakalanabilir. Bunu bir sonraki derste (özel exception sınıfları) detaylı işleyeceğiz.
Hatayı Yakalayıp Tekrar Fırlatmak — rethrow
void islemYap() {
try {
throw Exception("Bir sorun oluştu");
} catch (e) {
print("İşlem sırasında loglama yapılıyor: $e");
rethrow; // hatayı tekrar fırlat, çağıran taraf da yakalasın
}
}
void main() {
try {
islemYap();
} catch (e) {
print("main() içinde de yakalandı: $e");
}
}Çıktı:
İşlem sırasında loglama yapılıyor: Exception: Bir sorun oluştu
main() içinde de yakalandı: Exception: Bir sorun oluşturethrow, bir hatayı yakalayıp bir şey yaptıktan sonra (örneğin loglama), aynı hatayı tekrar fırlatmanı sağlar — böylece hatayı çağıran üst kod da haberdar olur. Bu, "hatayı burada gözlemle ama tamamen yutma, üst katmanlara da bildir" senaryolarında kullanılır.
Stack Trace — Hatanın Nerede Oluştuğunu Görme
void main() {
try {
int sonuc = 10 ~/ 0;
} catch (e, stackTrace) {
print("Hata: $e");
print("Nerede oluştu: $stackTrace");
}
}catch (e, stackTrace) şeklinde ikinci bir parametre alarak, hatanın kod içinde tam olarak nerede oluştuğuna dair bilgiyi (call stack — hangi fonksiyonun hangi fonksiyonu çağırdığı zinciri) alabilirsin. Bu, özellikle karmaşık uygulamalarda hata ayıklarken (debugging) çok değerlidir.
🎯 Bu Dersten Çıkarılması Gerekenler
try/catch, hata verebilecek kodu güvenli şekilde çalıştırmanı ve hatayı yakalayıp programın çökmesini engellemeni sağlar.on TipAdı, belirli bir hata tipini hedeflemeni sağlar; birden fazlaonbloğu sırayla kontrol edilir.finally, hata olsun olmasın her zaman çalışır — temizlik işlemleri için kullanılır.throw, kendi hatanı bilerek fırlatmanı sağlar; fonksiyonun çalışmasını anında durdurur.rethrow, bir hatayı yakalayıp işlem yaptıktan sonra tekrar fırlatmanı sağlar.catch (e, stackTrace), hatanın kod içinde nerede oluştuğuna dair detaylı bilgi verir.
📝 Ödevler
- [ ] Sıfıra bölme hatasını
try/catchile yakalayan ve kullanıcıya anlamlı bir mesaj gösteren bir örnek yaz. - [ ]
on FormatExceptionileint.parse()'ın geçersiz bir string ile çağrılmasını özel olarak yakala, genelcatchile diğer hataları ayrı yakala. - [ ]
finallybloğunun hem hata olduğunda hem olmadığında çalıştığını gösteren iki ayrı test senaryosu yaz. - [ ] Kendi
throw Exception(...)ifadeni kullanarak, negatif bir sayı girildiğinde hata fırlatan bir fonksiyon yaz,main()içinde yakala. - [ ]
rethrowkullanarak, bir hatayı iç fonksiyonda loglayıp dış fonksiyonda tekrar yakalayan iki seviyeli bir örnek yaz.
Sıradaki konu: Bölüm 8 — Konu 39: Özel Exception Sınıfları Yazma