Tüm Yazılar
KategoriDart
Okuma Süresi
27 dk okuma
Yayın Tarihi
...
Kelime Sayısı
2.360kelime

Kahveni hazırla - bu içerikli bir makale!

Dart 3 ile gelen records, patterns, sealed class, class modifiers, switch expressions ve diger modern ozellikler. Migration rehberi ve best practices.

Dart 3 Yenilikleri ve Modern Ozellikler: Eksiksiz Rehber

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


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 gerekiyordu
2class 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 temiz
13(int min, int max) findMinMax(List numbers) {
14 return (numbers.reduce(min), numbers.reduce(max));
15}
16 
17// Kullanim
18void 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 records
25({String name, int age, String email}) createUser() {
26 return (name: 'Ahmet', age: 28, email: '[email protected]');
27}
28 
29// Record type alias
30typedef 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 saglar
37void 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 turleri
2 
3// 1. Variable pattern
4var (x, y) = (10, 20);
5print('x=$x, y=$y'); // x=10, y=20
6 
7// 2. List pattern
8var [a, b, c] = [1, 2, 3];
9print('$a $b $c'); // 1 2 3
10 
11// 3. Map pattern
12var {'name': name, 'age': age} = {'name': 'Ali', 'age': 25};
13print('$name, $age'); // Ali, 25
14 
15// 4. Object pattern
16class 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], 5
30 
31// 6. Wildcard pattern (_)
32var (name2, _) = ('Veli', 30); // age'i yoksay
33print(name2); // Veli
34 
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 parsing
2Map 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 matching
12List 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 statement
2String 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 expression
16String 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 kullanim
24Widget 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 expression
32String 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 tanimi
2sealed 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 durumlari
27sealed 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 kullanimi
51class UserNotifier extends Notifier> {
52 @override
53 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 edebilirsin
10class Dog extends Animal {
11 Dog(super.name);
12 
13 @override
14 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 EDEBILIRSIN
26class ConsoleLogger implements Logger {
27 @override
28 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 edilebilir
35final 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 kullanilabilir
46mixin class Printable {
47 void prettyPrint() => print(toString());
48}
49 
50class User with Printable {
51 final String name;
52 User(this.name);
53 
54 @override
55 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 kullanma
2void processResponse(Map json) {
3 // ONCESI
4 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-case
19void 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 matching
28void processUsers(List> users) {
29 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 destructuring
2final (lat, lng) = getCoordinates();
3print('Enlem: $lat, Boylam: $lng');
4 
5// List destructuring
6final [first, second, ...rest] = [1, 2, 3, 4, 5];
7print('Ilk: $first, Ikinci: $second, Kalan: $rest');
8 
9// Object destructuring
10final Point(:x, :y) = getOrigin();
11print('x=$x, y=$y');
12 
13// Nested destructuring
14final 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 records
20var (a, b) = (1, 2);
21(a, b) = (b, a); // Degisken takas!
22print('a=$a, b=$b'); // a=2, b=1

9. 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 handling
5String? getName() => null;
6 
7void main() {
8 final name = getName();
9 
10 // Pattern matching ile null check
11 if (name case String validName) {
12 print('Isim: $validName');
13 } else {
14 print('Isim bos');
15 }
16 
17 // Switch ile null handling
18 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 guncelle
2# pubspec.yaml'da:
3# environment:
4# sdk: '>=3.0.0 <4.0.0'
5 
6# 2. Paketleri guncelle
7flutter pub upgrade --major-versions
8 
9# 3. Analiz calistir
10dart analyze
11 
12# 4. Derleme testi
13flutter build apk

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

Etiketler

#Dart#Dart 3#Records#Patterns#Sealed Class#Flutter#Programming
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz