Dart 3.0, dilin tarihindeki en buyuk guncellemedir. Records, pattern matching, sealed class'lar ve class modifier'lar ile Dart, modern programlama dillerinin en guclu ozelliklerini bunyesine katiyor. Bu guncelleme sadece yeni syntax degil — yazilim tasarim sekilinizi kokunden degistirecek ozellikler getiriyor.
Bu rehberde Dart 3'un tum yeniliklerini detayli orneklerle inceleyecegiz. Her ozellik icin "neden gerekli", "nasil kullanilir" ve "ne zaman kullanilmali" sorularini cevaplayacagiz.
Not: Dart 3.0+ ve Flutter 3.10+ gerektirir. Tum ornekler Dart 3.4 ile test edilmistir.
Icindekiler
- Dart 3 Genel Bakis
- Records (Kayitlar)
- Pattern Matching
- Switch Expressions
- Sealed Classes
- Class Modifiers
- If-Case ve Guard Clauses
- Destructuring
- Sound Null Safety %100
- Migration Rehberi
- Best Practices
- Sonuc ve Oneriler
1. Dart 3 Genel Bakis
Dart 3, uc buyuk pillar uzerine insa edilmistir:
Dart 3 Yenilik Tablosu
Ozellik | Kategori | Etki Seviyesi | Zorluk |
|---|---|---|---|
**Records** | Veri | Yuksek | Kolay |
**Patterns** | Kontrol Akisi | Cok Yuksek | Orta |
**Switch Expressions** | Kontrol Akisi | Yuksek | Kolay |
**Sealed Classes** | Tip Sistemi | Yuksek | Orta |
**Class Modifiers** | Tip Sistemi | Orta | Kolay |
**If-Case** | Kontrol Akisi | Orta | Kolay |
**Destructuring** | Veri | Yuksek | Kolay |
**Exhaustiveness** | Guvenlik | Cok Yuksek | Otomatik |
Neden Dart 3?
Dart 3 oncesinde bazi seyler gercekten zordu:
- Bir fonksiyondan birden fazla deger dondurme (tuple yoktu)
- Karmasik veri yapilarini tip-guvenli sekilde eslestirme
- Derleme zamaninda tum durumlarin ele alindigini garanti etme
Dart 3 bu sorunlarin hepsini zarifce cozuyor.
2. Records (Kayitlar)
Records, birden fazla degeri tek bir nesnede gruplama imkani verir. Tuple'larin Dart versiyonu olarak dusunebilirsiniz, ama daha guclu.
dart
1// ONCESI (Dart 2): Birden fazla deger dondurmek icin sinif gerekiyordu2class MinMax {3 final int min;4 final int max;5 MinMax(this.min, this.max);6}7 8MinMax findMinMax(List numbers) { 9 return MinMax(numbers.reduce(min), numbers.reduce(max));10}11 12// SONRASI (Dart 3): Record ile cok daha temiz13(int min, int max) findMinMax(List numbers) { 14 return (numbers.reduce(min), numbers.reduce(max));15}16 17// Kullanim18void main() {19 final result = findMinMax([3, 1, 4, 1, 5, 9, 2, 6]);20 print('Min: ${result.min}, Max: ${result.max}'); // Adli erisim (named)21 print('Min: ${result.$1}, Max: ${result.$2}'); // Konumsal erisim (positional)22}23 24// Named records25({String name, int age, String email}) createUser() {26 return (name: 'Ahmet', age: 28, email: '[email protected]');27}28 29// Record type alias30typedef UserRecord = ({String name, int age, String email});31 32UserRecord getUser() {33 return (name: 'Mehmet', age: 32, email: '[email protected]');34}35 36// Record'lar immutable ve value-based equality saglar37void main() {38 final a = (1, 'hello');39 final b = (1, 'hello');40 print(a == b); // true! (referans degil, deger karsilastirmasi)41}Record Kullanim Alanlari
- Fonksiyondan birden fazla deger dondurme
- Map entry'leri yerine tip-guvenli alternatif
- Gecici veri gruplama (sinif olusturmaya gerek yok)
- Pattern matching ile destructuring
Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
3. Pattern Matching
Pattern matching, Dart 3'un en guclu ozelligidir. Verileri eslestirme, ayristirma ve dogrulama islemlerini tek bir syntax ile yapar:
dart
1// Temel pattern turleri2 3// 1. Variable pattern4var (x, y) = (10, 20);5print('x=$x, y=$y'); // x=10, y=206 7// 2. List pattern8var [a, b, c] = [1, 2, 3];9print('$a $b $c'); // 1 2 310 11// 3. Map pattern12var {'name': name, 'age': age} = {'name': 'Ali', 'age': 25};13print('$name, $age'); // Ali, 2514 15// 4. Object pattern16class Point {17 final int x;18 final int y;19 Point(this.x, this.y);20}21 22void printPoint(Point p) {23 var Point(x: px, y: py) = p;24 print('($px, $py)');25}26 27// 5. Rest pattern (...)28var [first, ...rest, last] = [1, 2, 3, 4, 5];29print('$first, $rest, $last'); // 1, [2, 3, 4], 530 31// 6. Wildcard pattern (_)32var (name2, _) = ('Veli', 30); // age'i yoksay33print(name2); // Veli34 35// 7. Guard clause (when)36String classify(int value) {37 return switch (value) {38 int n when n < 0 => 'negatif',39 0 => 'sifir',40 int n when n > 0 && n < 100 => 'kucuk pozitif',41 _ => 'buyuk pozitif',42 };43}Gercek Dunya Ornegi: JSON Parsing
dart
1// Dart 3 pattern matching ile JSON parsing2Map parseApiResponse(Map json) { 3 return switch (json) {4 {'status': 'success', 'data': Map data} => data,5 {'status': 'error', 'message': String msg} => throw ApiException(msg),6 {'status': 'loading'} => throw StateException('Hala yukleniyor'),7 _ => throw FormatException('Bilinmeyen format'),8 };9}10 11// Liste icinde pattern matching12List extractNames(List items) { 13 return [14 for (final item in items)15 if (item case {'name': String name, 'active': true})16 name,17 ];18}4. Switch Expressions
Switch artik bir ifade (expression) olarak kullanilabilir — yani deger dondurur:
dart
1// ONCESI (Dart 2): switch statement2String getStatusText(Status status) {3 switch (status) {4 case Status.idle:5 return 'Bekliyor';6 case Status.loading:7 return 'Yukleniyor';8 case Status.success:9 return 'Basarili';10 case Status.error:11 return 'Hata';12 }13}14 15// SONRASI (Dart 3): switch expression16String getStatusText(Status status) => switch (status) {17 Status.idle => 'Bekliyor',18 Status.loading => 'Yukleniyor',19 Status.success => 'Basarili',20 Status.error => 'Hata',21};22 23// Widget icinde kullanim24Widget buildStatusIcon(Status status) => switch (status) {25 Status.idle => const Icon(Icons.hourglass_empty, color: Colors.grey),26 Status.loading => const CircularProgressIndicator(),27 Status.success => const Icon(Icons.check_circle, color: Colors.green),28 Status.error => const Icon(Icons.error, color: Colors.red),29};30 31// Karmasik pattern'ler ile switch expression32String describeNumber(num value) => switch (value) {33 0 => 'sifir',34 double d when d < 0 => 'negatif ondalik: $d',35 double d when d > 0 => 'pozitif ondalik: $d',36 int i when i < 0 => 'negatif tam sayi: $i',37 int i when i > 0 => 'pozitif tam sayi: $i',38 _ => 'bilinmiyor',39};5. Sealed Classes
Sealed class'lar, sinifin alt tiplerini sinirlar ve exhaustiveness checking saglar:
dart
1// Sealed class tanimi2sealed class Result {} 3 4class Success extends Result { 5 final T data;6 Success(this.data);7}8 9class Loading extends Result {} 10 11class Error extends Result { 12 final String message;13 final Exception? exception;14 Error(this.message, [this.exception]);15}16 17// Exhaustive switch: Tum durumlar ele alinmali!18// Bir durum eksik kalirsa derleyici HATA verir.19Widget buildResult(Result result) => switch (result) { 20 Success(data: final user) => Text('Hosgeldin ${user.name}'),21 Loading() => const CircularProgressIndicator(),22 Error(message: final msg) => Text('Hata: $msg'),23 // Yeni bir Result alt tipi eklenirse, derleyici burada uyarir!24};25 26// Gercek dunya ornegi: API durumlari27sealed class ApiState { 28 const ApiState();29}30 31class ApiInitial extends ApiState { 32 const ApiInitial();33}34 35class ApiLoading extends ApiState { 36 const ApiLoading();37}38 39class ApiSuccess extends ApiState { 40 final T data;41 const ApiSuccess(this.data);42}43 44class ApiError extends ApiState { 45 final String message;46 final int? statusCode;47 const ApiError(this.message, {this.statusCode});48}49 50// Riverpod ile sealed class kullanimi51class UserNotifier extends Notifier> { 52 @override53 ApiState build() => const ApiInitial(); 54 55 Future fetchUser(String id) async { 56 state = const ApiLoading();57 try {58 final user = await ref.read(userRepositoryProvider).getUser(id);59 state = ApiSuccess(user);60 } catch (e) {61 state = ApiError(e.toString());62 }63 }64}Sealed vs Abstract vs Enum Karsilastirmasi
Ozellik | enum | abstract class | sealed class |
|---|---|---|---|
**Alt tip siniri** | Sabit degerler | Sinirsiz | Ayni dosyada |
**Exhaustiveness** | Evet | Hayir | Evet |
**Veri tasima** | Sinirli | Evet | Evet |
**Pattern matching** | Evet | Kismen | Tam destek |
**Kullanim** | Sabit durumlar | Genel soyutlama | Durumlu tip hiyerarsisi |
6. Class Modifiers
Dart 3 ile sinif tanimlarina yeni modifier'lar eklendi:
dart
1// base: Sadece extend edilebilir (implement YAPILAMAZ)2base class Animal {3 final String name;4 Animal(this.name);5 6 void makeSound() => print('...');7}8 9// base class Animal'i extend edebilirsin10class Dog extends Animal {11 Dog(super.name);12 13 @override14 void makeSound() => print('Hav hav!');15}16 17// AMA implement EDEMEZSIN:18// class FakeAnimal implements Animal {} // DERLEME HATASI!19 20// interface: Sadece implement edilebilir (extend YAPILAMAZ)21interface class Logger {22 void log(String message);23}24 25// implement EDEBILIRSIN26class ConsoleLogger implements Logger {27 @override28 void log(String message) => print('[LOG] $message');29}30 31// AMA extend EDEMEZSIN:32// class SpecialLogger extends Logger {} // DERLEME HATASI!33 34// final: Ne extend ne implement edilebilir35final class DatabaseConfig {36 final String host;37 final int port;38 const DatabaseConfig({required this.host, required this.port});39}40 41// NE extend NE implement:42// class MyConfig extends DatabaseConfig {} // HATA!43// class FakeConfig implements DatabaseConfig {} // HATA!44 45// mixin class: Hem mixin hem class olarak kullanilabilir46mixin class Printable {47 void prettyPrint() => print(toString());48}49 50class User with Printable {51 final String name;52 User(this.name);53 54 @override55 String toString() => 'User($name)';56}Class Modifier Karar Tablosu
Modifier | extend | implement | mixin | Ne Zaman |
|---|---|---|---|---|
(yok) | Evet | Evet | Hayir | Varsayilan |
**base** | Evet | Hayir | Hayir | API koruması |
**interface** | Hayir | Evet | Hayir | Kontrat tanimla |
**final** | Hayir | Hayir | Hayir | Tamamen kilitle |
**sealed** | Evet* | Hayir | Hayir | Exhaustive check |
**mixin** | Hayir | Hayir | Evet | Davranis paylasimi |
*sealed class'lar sadece ayni dosyada extend edilebilir.
7. If-Case ve Guard Clauses
dart
1// If-case: Pattern matching'i if bloklarinda kullanma2void processResponse(Map json) { 3 // ONCESI4 if (json.containsKey('data') && json['data'] is Map) {5 final data = json['data'] as Map; 6 final name = data['name'] as String?;7 if (name != null) {8 print('Kullanici: $name');9 }10 }11 12 // SONRASI (Dart 3)13 if (json case {'data': {'name': String name}}) {14 print('Kullanici: $name');15 }16}17 18// Guard clause ile if-case19void processAge(Map data) { 20 if (data case {'age': int age} when age >= 18) {21 print('Yetiskin: $age');22 } else {23 print('Gecersiz veya rexit alti');24 }25}26 27// For dongusu icinde pattern matching28void processUsers(List29 for (final {'name': String name, 'active': bool active} in users) {30 if (active) {31 print('Aktif kullanici: $name');32 }33 }34}8. Destructuring
dart
1// Record destructuring2final (lat, lng) = getCoordinates();3print('Enlem: $lat, Boylam: $lng');4 5// List destructuring6final [first, second, ...rest] = [1, 2, 3, 4, 5];7print('Ilk: $first, Ikinci: $second, Kalan: $rest');8 9// Object destructuring10final Point(:x, :y) = getOrigin();11print('x=$x, y=$y');12 13// Nested destructuring14final user = {'name': 'Ayse', 'address': {'city': 'Istanbul', 'zip': '34000'}};15if (user case {'name': String name, 'address': {'city': String city}}) {16 print('$name, $city');17}18 19// Swap variables with records20var (a, b) = (1, 2);21(a, b) = (b, a); // Degisken takas!22print('a=$a, b=$b'); // a=2, b=19. Sound Null Safety %100
Dart 3 ile null safety artik zorunludur. Tum paketler null-safe olmalidir:
dart
1// Dart 3'te null safety kacilamaz!2// Artik --no-sound-null-safety flagi CALISMAZ.3 4// Dogru null handling5String? getName() => null;6 7void main() {8 final name = getName();9 10 // Pattern matching ile null check11 if (name case String validName) {12 print('Isim: $validName');13 } else {14 print('Isim bos');15 }16 17 // Switch ile null handling18 final result = switch (name) {19 String n when n.isNotEmpty => 'Isim: $n',20 String _ => 'Bos string',21 null => 'null deger',22 };23}10. Migration Rehberi
Dart 2'den Dart 3'e gecis adimlari:
bash
1# 1. Dart versiyonunu guncelle2# pubspec.yaml'da:3# environment:4# sdk: '>=3.0.0 <4.0.0'5 6# 2. Paketleri guncelle7flutter pub upgrade --major-versions8 9# 3. Analiz calistir10dart analyze11 12# 4. Derleme testi13flutter build apkMigration Kontrol Listesi
Adim | Detay | Oncelik |
|---|---|---|
SDK constraint guncelle | >=3.0.0 <4.0.0 | KRITIK |
Paketleri guncelle | pub upgrade --major-versions | KRITIK |
Null safety migrasyon | --no-sound-null-safety kaldir | KRITIK |
Records kullan | Tuple siniflarini degistir | ORTA |
Sealed class | Abstract + enum yerine | ORTA |
Pattern matching | Karmasik if/switch yerine | DUSUK |
Class modifiers | API sinirlari icin | DUSUK |
11. Best Practices
- Records: kullanarak gereksiz sinif tanimlarindan kacinin
- Sealed class: ile durumlu tip hiyerarsileri olusturun (exhaustive check bonusu)
- Switch expression: ile temiz ve okunakli kontrol akisi yazin
- Pattern matching: ile karmasik veri yapilarini zarifce cozumleyin
- Class modifiers: ile API sinirlari belirleyin
Sonuc ve Oneriler
Dart 3, dili tamamen yeni bir seviyeye tasiyor. Records, pattern matching ve sealed class'lar ile daha guvenli, okunakli ve test edilebilir kod yazabilirsiniz. Bu ozellikler sadece syntax sekeri degil — yazilim tasarim sekilinizi iyilestiren temel araclardir.
ALTIN İPUCU
Bu yazının en değerli bilgisi
Bu ipucu, yazının en önemli çıkarımını içeriyor.
Okuyucu Ödülü
Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var:

