↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 6 — Konu 30: Getter / Setter

3 dk okuma #dart
Dizi · 29/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 8 başlık
  1. Neden Getter/Setter'a İhtiyaç Var?
  2. Getter — Hesaplanmış Bir "Özellik" Tanımlama
  3. Setter — Bir Değeri Atarken Kontrol Uygulama
  4. _ (Alt Çizgi) — Private Alan/Metod Kuralı
  5. Neden Getter/Setter + Private Alan Kalıbı Bu Kadar Yaygın?
  6. Getter/Setter Olmadan Sadece Getter Tanımlamak — Basit Kalıp
  7. 🎯 Bu Dersten Çıkarılması Gerekenler
  8. 📝 Ödevler

Neden Getter/Setter'a İhtiyaç Var?

Bölüm 6'ya kadar, bir class'ın alanlarına doğrudan erişip değiştirebiliyorduk:

dart
class Dikdortgen {
  double genislik;
  double yukseklik;
  Dikdortgen(this.genislik, this.yukseklik);
}

void main() {
  Dikdortgen d = Dikdortgen(4, 5);
  d.genislik = -10; // ❌ mantıksal olarak hatalı ama Dart bunu engellemiyor!
  print(d.genislik); // -10 — negatif bir genişlik, anlamsız ama kabul edildi
}

Bu bir sorun — bir dikdörtgenin genişliği negatif olamaz, ama şu anki kodumuz bunu engelleyemiyor. Getter ve setter'lar, bir alana erişimi/değişimini kontrol altına almanı sağlayan mekanizmalardır.

Getter — Hesaplanmış Bir "Özellik" Tanımlama

dart
class Dikdortgen {
  double genislik;
  double yukseklik;

  Dikdortgen(this.genislik, this.yukseklik);

  double get alan {
    return genislik * yukseklik;
  }

  double get cevre => 2 * (genislik + yukseklik); // arrow ile kısa yazım
}

void main() {
  Dikdortgen d = Dikdortgen(4, 5);
  print(d.alan);  // 20.0 — parantez YOK, tıpkı bir alan gibi erişiliyor!
  print(d.cevre); // 18.0
}

Kritik detay: d.alan yazdık, d.alan() değil. Getter'lar, dışarıdan bakıldığında sıradan bir alan gibi görünür (parantezsiz erişilir), ama arka planda aslında bir metod gibi çalışır — her erişimde hesaplama yeniden yapılır.

Bunu neden bir alan olarak değil de getter olarak tanımlıyoruz? Çünkü alan, genislik ve yukseklik'ten türetilen bir değerdir — kendi başına saklanmasına gerek yoktur, her ihtiyaç duyulduğunda hesaplanabilir. Eğer alan'ı sıradan bir alan olarak tutsaydık, genislik her değiştiğinde alan'ı da elle güncellemen gerekirdi — bu, hataya çok açık bir yaklaşımdır (birini güncelleyip diğerini unutmak gibi). Getter, bu senkronizasyon sorununu tamamen ortadan kaldırır.

Setter — Bir Değeri Atarken Kontrol Uygulama

dart
class Dikdortgen {
  double _genislik; // alt çizgi ile başlıyor — "private" (birazdan açıklayacağız)

  Dikdortgen(this._genislik);

  double get genislik => _genislik;

  set genislik(double yeniDeger) {
    if (yeniDeger < 0) {
      print("Hata: Genişlik negatif olamaz, işlem reddedildi.");
      return;
    }
    _genislik = yeniDeger;
  }
}

void main() {
  Dikdortgen d = Dikdortgen(10);
  print(d.genislik); // 10.0

  d.genislik = 20; // setter çağrılıyor, parantez yok
  print(d.genislik); // 20.0

  d.genislik = -5; // setter içindeki kontrol devreye giriyor
  // Hata: Genişlik negatif olamaz, işlem reddedildi.
  print(d.genislik); // 20.0 — değişmedi!
}

Yapıyı parçalayalım:

  • _genislik — gerçek veriyi tutan private alan (alt çizgi ile başlıyor, birazdan açıklayacağız).
  • get genislik => _genislik; — dışarıya genislik adıyla okuma izni veren getter.
  • set genislik(double yeniDeger) { ... } — dışarıdan genislik'e yazma girişimini yakalayan, kontrol eden setter.

d.genislik = 20; yazdığında, aslında arka planda set genislik(20) metodun çalışıyor — ama sözdizimi olarak sanki doğrudan bir alana atama yapıyormuşsun gibi görünüyor. Bu, encapsulation (kapsülleme) dediğimiz OOP prensibinin temel bir uygulamasıdır: dış dünyaya basit bir arayüz (d.genislik) sunarken, arka planda kontrol mekanizmalarını gizli tutabiliyorsun.

_ (Alt Çizgi) — Private Alan/Metod Kuralı

Bölüm 1'de kısaca değindiğimiz alt çizgi kuralını burada tam olarak açıklayalım: Dart'ta, bir alan/metod/class adının başına _ koymak, onu o dosyaya (library) özel yapar — başka bir dosyadan doğrudan erişilemez hale gelir.

dart
// dikdortgen.dart dosyası
class Dikdortgen {
  double _genislik; // sadece bu dosya içinden erişilebilir
  Dikdortgen(this._genislik);
}
dart
// main.dart dosyası
import 'dikdortgen.dart';

void main() {
  Dikdortgen d = Dikdortgen(10);
  print(d._genislik); // ❌ HATA! Başka bir dosyadan private alana erişilemez
}

Bu, Java/C# gibi dillerdeki private anahtar kelimesine benzer bir işlev görür ama Dart'ta ayrı bir anahtar kelime yoktur — sadece isim kuralı (_ öneki) kullanılır. Bunun dosya (library) seviyesinde çalıştığını bilmen önemli — aynı dosya içindeki başka bir class, _genislik'e erişebilir, ama farklı bir dosyadaki class erişemez.

Neden Getter/Setter + Private Alan Kalıbı Bu Kadar Yaygın?

dart
class BankaHesabi {
  double _bakiye = 0;

  double get bakiye => _bakiye;

  void paraYatir(double miktar) {
    if (miktar <= 0) {
      print("Geçersiz miktar");
      return;
    }
    _bakiye += miktar;
  }

  void paraCek(double miktar) {
    if (miktar > _bakiye) {
      print("Yetersiz bakiye");
      return;
    }
    _bakiye -= miktar;
  }
}

void main() {
  BankaHesabi hesap = BankaHesabi();
  hesap.paraYatir(1000);
  print(hesap.bakiye); // 1000.0

  hesap.paraCek(2000); // Yetersiz bakiye
  print(hesap.bakiye); // 1000.0 — değişmedi

  hesap.bakiye = 5000; // ❌ HATA! bakiye için setter yok, sadece getter var
}

Bu örnek, çok önemli bir kalıbı gösteriyor: bakiye alanı için sadece getter tanımladık, setter tanımlamadık. Bu, bakiye'yi dışarıdan salt-okunur (read-only) yapıyor — değeri sadece paraYatir() ve paraCek() metodları aracılığıyla, kontrollü bir şekilde değiştirilebiliyor. Bu, gerçek dünyada bir banka hesabının nasıl çalışması gerektiğine çok benzer — bakiyeyi doğrudan "20000 yap" diyemezsin, sadece yatırma/çekme işlemleriyle değiştirebilirsin.

Getter/Setter Olmadan Sadece Getter Tanımlamak — Basit Kalıp

dart
class Kisi {
  final String ad;
  final String soyad;

  Kisi(this.ad, this.soyad);

  String get tamAd => "$ad $soyad"; // sadece getter, setter yok
}

void main() {
  Kisi k = Kisi("Ahmet", "Yılmaz");
  print(k.tamAd); // Ahmet Yılmaz

  k.tamAd = "Başka İsim"; // ❌ HATA! setter tanımlanmadı
}

tamAd, ad ve soyad'dan türetildiği için, ona doğrudan bir değer atamak zaten mantıksız olurdu — bu yüzden sadece getter tanımlamak, bu tür "salt hesaplanmış" özellikler için doğal ve doğru bir kalıptır.


🎯 Bu Dersten Çıkarılması Gerekenler

  • Getter (get), dışarıya bir alan gibi görünen ama aslında hesaplama yapan bir metoddur; parantezsiz çağrılır.
  • Setter (set), bir değeri atarken kontrol/doğrulama uygulamanı sağlar; nesne.alan = deger şeklinde çağrılır.
  • _ öneki, bir alan/metodu dosyaya (library) özel (private) yapar.
  • Yaygın kalıp: gerçek veriyi _alan olarak private tut, get/set ile kontrollü erişim sağla.
  • Sadece getter tanımlayıp setter tanımlamamak, bir özelliği dışarıdan salt-okunur yapmanın basit bir yoludur.

📝 Ödevler

  • [ ] Bir Daire sınıfı yaz — yaricap alanı olsun, alan ve cevre için getter'lar tanımla (hesaplanmış özellikler).
  • [ ] Bir Sicaklik sınıfı yaz — private bir _derece (Celsius) alanı olsun, negatif mutlak sıfırdan (-273.15) düşük bir değer atanmaya çalışıldığında reddeden bir setter yaz.
  • [ ] BankaHesabi örneğindeki gibi, sadece getter'ı olan (setter'ı olmayan) bir "salt-okunur" alan tasarla ve doğrudan atama yapmaya çalışarak hatayı gözlemle.
  • [ ] _ ile başlayan private bir alanı, aynı dosya içinde başka bir class'tan erişip erişemediğini test et (iki class'ı aynı dosyada tanımlayarak dene).
  • [ ] Sadece getter ile hesaplanan bir "tam ad" veya benzeri bir birleşik özellik tanımla, doğrudan atama yapmaya çalışıp hatayı gözlemle.

Sıradaki konu: Bölüm 6 — Konu 31: Statik Üyeler (static)