↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 8 — Konu 38: `try / catch / finally`, `throw`

3 dk okuma #dart
Dizi · 37/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 11 başlık
  1. Exception (İstisna) Nedir?
  2. try / catch — İstisnayı Yakalama
  3. catch ile Hata Tipini Belirtme — on
  4. on ve catch'i Birlikte Kullanma — Hem Tip Hem Detay
  5. finally — Her Durumda Çalışan Blok
  6. throw — Kendi Hatanı Fırlatmak
  7. throw ile Herhangi Bir Değer Fırlatılabilir mi?
  8. Hatayı Yakalayıp Tekrar Fırlatmak — rethrow
  9. Stack Trace — Hatanın Nerede Oluştuğunu Görme
  10. 🎯 Bu Dersten Çıkarılması Gerekenler
  11. 📝 Ö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.

dart
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

dart
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ı:

metin
Bir hata oluştu: IntegerDivisionByZeroException
Program devam ediyor!

Yapıyı parçalayalım:

  • try { ... } — hata verebilecek kodu buraya yazarsın.
  • catch (e) { ... } — eğer try bloğ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

dart
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:

dart
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

dart
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

dart
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ı:

metin
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.

dart
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:

dart
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ı:

metin
Hata yakalandı: Exception: Yaş negatif olamaz

throw, 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?

dart
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

dart
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ı:

metin
İşlem sırasında loglama yapılıyor: Exception: Bir sorun oluştu
main() içinde de yakalandı: Exception: Bir sorun oluştu

rethrow, 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

dart
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 fazla on bloğ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/catch ile yakalayan ve kullanıcıya anlamlı bir mesaj gösteren bir örnek yaz.
  • [ ] on FormatException ile int.parse()'ın geçersiz bir string ile çağrılmasını özel olarak yakala, genel catch ile diğer hataları ayrı yakala.
  • [ ] finally bloğ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.
  • [ ] rethrow kullanarak, 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