Menu
Coddy logo textTech

Late Anahtar Kelimesi ve Null Safety

Coddy'nin Dart Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 26 / 110.

Bazen null olamayan (non-nullable) bir değişkene ihtiyaç duyarsınız, ancak değerini hemen atayamazsınız. late anahtar kelimesi Dart'a "Bunu kullanmadan önce başlatacağıma söz veriyorum." der.

late String description;

void setup() {
  description = 'Initialized later';
}

void main() {
  setup();
  print(description);  // Çalışır - kullanımdan önce başlatıldı
}

late olmadan, Dart description değişkeninin başlatılmadığından şikayet ederdi. late ile, erişimden önce bir değere sahip olduğundan emin olma sorumluluğunu siz üstlenirsiniz. Eğer başlatmadan önce okumaya çalışırsanız, bir çalışma zamanı hatası alırsınız.

Yaygın bir kullanım durumu, gerçekten ihtiyaç duyulana kadar ertelemek istediğiniz maliyetli hesaplamalardır:

class DataProcessor {
  late List<int> data = _loadData();
  
  List<int> _loadData() {
    print('Loading data...');
    return [1, 2, 3, 4, 5];
  }
}

DataProcessor processor = DataProcessor();
// 'Loading data...' henüz yazdırılmadı
print(processor.data);  // Şimdi yüklenir ve yazdırılır

_loadData() yöntemi, nesne oluşturulduğunda değil, yalnızca data öğesine ilk kez erişildiğinde çalışır. Bu tembel başlatma (lazy initialization), değere hiç ihtiyaç duyulmayabileceği durumlarda performansı artırabilir.

Bir değişkenin kullanılmadan önce ilklendirileceğinden emin olduğunuz ancak bunu bildirim anında yapamadığınız durumlarda late kullanın. Bu, derleyiciye verilmiş bir sözdür; bu sözü bozarsanız programınız çöker.

challenge icon

Görev

Kolay

Ertelenmiş başlatma için late değişkenlerinin gücünü gösteren bir yapılandırma yöneticisi oluşturalım. Yapılandırmanın gerçekten ihtiyaç duyulduğu ana kadar maliyetli kurulum işlemlerinin gerçekleşmediği bir sistem oluşturacaksınız.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • config_manager.dart: Uygulama ayarlarını yöneten bir ConfigManager sınıfı tanımlayın. Sınıf şunlara sahip olmalıdır:
    • Yapıcı (constructor) aracılığıyla iletilen bir String appName
    • Daha sonra bir kurulum yöntemi aracılığıyla başlatılacak olan bir late String databaseUrl
    • İlk erişildiğinde Calculating max connections... yazdıran ve 100 değerini döndüren, tembel başlatmalı (lazy initialization) bir late int maxConnections
    • databaseUrl değişkenini başlatan bir setupDatabase(String url) metodu
    • Mevcut yapılandırmayı yazdıran bir displayConfig() metodu
  • main.dart: Yapılandırma yöneticinizi içe aktarın ve late değişkenlerin nasıl çalıştığını gösterin:
    • Uygulama adı 'MyApp' olan bir ConfigManager oluşturun
    • Config created yazdırın
    • 'localhost:5432/mydb' URL'si ile setupDatabase metodunu çağırın
    • Accessing max connections... yazdırın
    • maxConnections değerini yazdırın
    • Accessing max connections again... yazdırın
    • maxConnections değerini tekrar yazdırın (hesaplama mesajının tekrarlanmadığına dikkat edin)
    • displayConfig() metodunu çağırın

displayConfig() metodu şu formatta yazdırmalıdır:

--- Configuration ---
App: [appName]
Database: [databaseUrl]
Max Connections: [maxConnections]

Tembel (lazy) maxConnections hesaplamasının yalnızca bir kez -ona ilk eriştiğinizde- nasıl çalıştığına dikkat edin. Bu, bir başlatıcı ile birlikte late kullanmanın avantajıdır!

Beklenen çıktı:

Config created
Accessing max connections...
Calculating max connections...
100
Accessing max connections again...
100
--- Configuration ---
App: MyApp
Database: localhost:5432/mydb
Max Connections: 100

Kopya kağıdı

late anahtar kelimesi, kullanılmadan önce daha sonra başlatılacak olan null yapılamaz (non-nullable) değişkenler tanımlamanıza olanak tanır:

late String description;

void setup() {
  description = 'Initialized later';
}

void main() {
  setup();
  print(description);  // Works - initialized before use
}

late olmadan, Dart anında başlatma gerektirir. late ile, değişkene erişmeden önce onu başlatacağınıza dair söz verirsiniz. Başlatılmamış bir late değişkenini okumak, çalışma zamanı hatasına (runtime error) neden olur.

Tembel Başlatma (Lazy Initialization): Bir late değişkeninin bir başlatıcısı (initializer) olduğunda, başlatma işlemi değişkene ilk kez erişilene kadar ertelenir:

class DataProcessor {
  late List<int> data = _loadData();
  
  List<int> _loadData() {
    print('Loading data...');
    return [1, 2, 3, 4, 5];
  }
}

DataProcessor processor = DataProcessor();
// 'Loading data...' hasn't printed yet
print(processor.data);  // Now it loads and prints

_loadData() yöntemi, nesne oluşturulduğunda değil, yalnızca data değişkenine ilk kez erişildiğinde çalışır. Bu, değerin hiç gerekmediği durumlarda veya başlatma işleminin maliyetli olduğu durumlarda performansı artırır.

Kendin dene

import 'config_manager.dart';

void main() {
  // TODO: 'MyApp' uygulama adıyla bir ConfigManager oluşturun
  
  // TODO: 'Config created' yazdırın
  
  // TODO: 'localhost:5432/mydb' URL'si ile setupDatabase'i çağırın
  
  // TODO: 'Accessing max connections...' yazdırın
  
  // TODO: maxConnections değerini yazdırın
  
  // TODO: 'Accessing max connections again...' yazdırın
  
  // TODO: maxConnections değerini tekrar yazdırın
  // (hesaplama mesajının tekrarlanmadığına dikkat edin)
  
  // TODO: displayConfig() fonksiyonunu çağırın
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler