Bölüm 7 — Konu 34: Soyut Sınıflar (`abstract class`)
Dizi · 33/64 Dart Türkçe Tutorial
- Bölüm 1 — Konu 1: Dart Nedir, Nerede Kullanılır, Neden Flutter Bu Dili Seçti
- Bölüm 1 — Konu 2: Ortam Kurulumu (Dart SDK, DartPad, Terminal ile Çalıştırma)
- Bölüm 1 — Konu 3: İlk Program (`main()`, `print()`, Dosya Yapısı)
- Bölüm 1 — Konu 4: Yorum Satırları, Temel Sözdizimi Kuralları
- Bölüm 2 — Konu 5: Değişken Tanımlama — `var`, `final`, `const` Farkı
- Bölüm 2 — Konu 6: Temel Tipler — `int`, `double`, `String`, `bool`
- Bölüm 2 — Konu 7: Tip Çıkarımı (Type Inference) ve Açık Tip Belirtme
- Bölüm 2 — Konu 8: `dynamic` ve `Object` — Ne Zaman Kullanılır, Ne Zaman Kaçınılır
- Bölüm 2 — Konu 9: Null Safety Temelleri (`?`, `!`, `late`'e Giriş)
- Bölüm 3 — Konu 10: Aritmetik, Atama, Karşılaştırma, Mantıksal Operatörler
- Bölüm 3 — Konu 11: `if / else if / else`
- Bölüm 3 — Konu 12: `switch` / `switch expression` (Modern Dart)
- Bölüm 3 — Konu 13: Ternary Operatör, `??`, `??=`, `?.`
- Bölüm 3 — Konu 14: `for`, `while`, `do-while` Döngüleri
- Bölüm 4 — Konu 16: `List` — Oluşturma, Erişim, Temel Metodlar
- Bölüm 4 — Konu 17: `Set` — Benzersiz Eleman Mantığı
- Bölüm 4 — Konu 18: `Map` — Key-Value Yapılar
- Bölüm 4 — Konu 19: Koleksiyon Üzerinde `for-in`, `forEach`
- Bölüm 4 — Konu 20: Spread Operatörü (`...`, `...?`) ve Collection If/For
- Bölüm 5 — Konu 21: Fonksiyon Tanımlama, Parametreler (Positional, Named, Optional)
- Bölüm 5 — Konu 22: Varsayılan Parametre Değerleri (Derinlemesine)
- Bölüm 5 — Konu 23: Arrow Function (`=>`) Sözdizimi
- Bölüm 5 — Konu 24: Fonksiyonlar Birinci Sınıf Vatandaş — Değişkene Atama, Parametre Olarak Geçme
- Bölüm 5 — Konu 25: Anonim Fonksiyonlar ve Closure Kavramı (Derinlemesine)
- Bölüm 5 — Konu 26: Recursion (Özyineleme)
- Bölüm 6 — Konu 27: Class Tanımlama, Constructor (Varsayılan, Named, Factory)
- Bölüm 6 — Konu 28: Alanlar (Fields), Metodlar, `this` Kullanımı (Derinlemesine)
- Bölüm 6 — Konu 29: Initializer List, Constructor Kısayolları (Derinlemesine)
- Bölüm 6 — Konu 30: Getter / Setter
- Bölüm 6 — Konu 31: Statik Üyeler (`static`)
- Bölüm 7 — Konu 32: Kalıtım (`extends`), `super` Kullanımı
- Bölüm 7 — Konu 33: Metod Override Etme, `@override`
- Bölüm 7 — Konu 34: Soyut Sınıflar (`abstract class`)
- Bölüm 7 — Konu 35: Interface Mantığı (`implements`)
- Bölüm 7 — Konu 36: Mixin (`with`)
- Bölüm 7 — Konu 37: `enum` — Basit ve Gelişmiş (Metotlu Enum'lar)
- Bölüm 8 — Konu 38: `try / catch / finally`, `throw`
- Bölüm 8 — Konu 39: Özel Exception Sınıfları Yazma
- Bölüm 8 — Konu 40: Sound Null Safety Derinlemesine — `late`, `required`, Non-Nullable Varsayılan Davranış
- Bölüm 8 — Konu 41: `assert` ile Geliştirme Zamanı Kontrolleri
- Bölüm 9 — Konu 42: Generic Sınıflar ve Fonksiyonlar
- Bölüm 9 — Konu 43: Generic Sınırlamalar (`<T extends ...>`)
- Bölüm 9 — Konu 44: Dart'ın Built-in Generic Koleksiyonları Nasıl Çalışır
- Bölüm 10 — Konu 45: `Future` Kavramı, `async`/`await`
- Bölüm 10 — Konu 46: `Future.then`, Hata Yönetimi (`catchError`)
- Bölüm 10 — Konu 47: `Stream` Temelleri, `async*`, `yield`
- Bölüm 10 — Konu 48: `StreamController`, Broadcast Stream
- Bölüm 11 — Konu 49: `map`, `where`, `reduce`, `fold`
- Bölüm 11 — Konu 50: `sort`, Custom Comparator ile Sıralama
- Bölüm 11 — Konu 51: Iterable Kavramı Derinlemesine (Lazy Evaluation)
- Bölüm 11 — Konu 52: Cascade Notasyonu (`..`)
- Bölüm 12 — Konu 53: `pubspec.yaml`, pub.dev'den Paket Ekleme
- Bölüm 12 — Konu 54: Kütüphane Oluşturma, `import`/`export`, `part`/`part of`
- Bölüm 12 — Konu 55: Dart'ta Test Yazımı (`test` Paketi, Unit Test Mantığı)
- Bölüm 12 — Konu 56: Extension Methods
- Bölüm 12 — Konu 57: Dart'ın Derleme Modelleri (JIT vs AOT) ve Bunun Flutter'a Etkisi
- Bölüm 13 — Konu 59: Dart 3 Pattern Matching — Records, Destructuring, Sealed Classes, Exhaustive Switch
- Bölüm 13 — Konu 60: `Never` Tipi, `covariant` ve Generic Variance Detayları
- Bölüm 13 — Konu 61: Event Loop Derinlemesine — Microtask Queue vs Event Queue
- Bölüm 13 — Konu 62: Memory Model & Performans — Garbage Collection, `const` Nesnelerin Bellek Avantajı
- Bölüm 13 — Konu 63: Isolate'ler Arası Mesajlaşmanın Maliyeti ve `compute()`'un İç İşleyişi
- Bölüm 13 — Konu 64: FFI (Foreign Function Interface) — C Koduna Erişim
- Bölüm 13 — Konu 65: Sunucu Tarafında Dart — `dart:io`, `shelf` Paketiyle Basit Bir Backend/CLI Aracı Yazma
- Bölüm 13 — Konu 66: Derleyici & Analiz Araçları — `dart analyze`, Custom Lint Kuralları, `build_runner` Mimarisi
İçindekiler 9 başlık
Soyut Sınıf Nedir?
Bazen bir üst sınıf yazarsın ama bu sınıftan hiçbir zaman doğrudan bir nesne oluşturulmasını istemezsin — sadece diğer sınıfların ondan türemesi (extend etmesi) için var olmasını istersin. Bu tür sınıflara soyut sınıf (abstract class) denir.
abstract class Sekil {
double alanHesapla(); // gövde YOK, sadece imza — "soyut metod"
}
void main() {
Sekil s = Sekil(); // ❌ HATA! soyut sınıftan nesne oluşturulamaz
}abstract anahtar kelimesi, bu sınıfın doğrudan Sekil() ile bir nesne oluşturmak için kullanılamayacağını belirtir. Neden? Çünkü alanHesapla() metodunun gövdesi (implementasyonu) yok — sadece "her Sekil'in bir alanHesapla metodu olmalı" diyoruz, ama bunun nasıl hesaplanacağını belirtmiyoruz (çünkü bir dairenin alanı ile bir karenin alanı tamamen farklı formüllerle hesaplanır — genel bir "şekil" için tek bir formül yazmak anlamsız).
Soyut Metod (Abstract Method)
abstract class Sekil {
double alanHesapla(); // soyut metod — sadece imza, noktalı virgülle biter
void bilgiVer() { // normal (somut/concrete) metod — gövdesi var
print("Bu şeklin alanı: ${alanHesapla()}");
}
}Bir soyut sınıf, hem soyut metodlar (gövdesiz) hem de somut metodlar (gövdeli) içerebilir. bilgiVer(), alanHesapla()'yı çağırıyor — ama alanHesapla()'nın gerçek implementasyonunu henüz bilmiyor. Bu, alt sınıfların sorumluluğudur.
Soyut Sınıftan Türeme — Zorunlu Implementasyon
abstract class Sekil {
double alanHesapla();
void bilgiVer() {
print("Bu şeklin alanı: ${alanHesapla()}");
}
}
class Daire extends Sekil {
double yaricap;
Daire(this.yaricap);
@override
double alanHesapla() => 3.14159 * yaricap * yaricap;
}
class Kare extends Sekil {
double kenar;
Kare(this.kenar);
@override
double alanHesapla() => kenar * kenar;
}
void main() {
Daire d = Daire(5);
Kare k = Kare(4);
d.bilgiVer(); // Bu şeklin alanı: 78.53975
k.bilgiVer(); // Bu şeklin alanı: 16.0
}Kritik kural: Sekil'den türeyen her sınıf (Daire, Kare), alanHesapla() metodunu mutlaka implemente etmek (override etmek) zorundadır. Eğer implemente etmezsen:
class UcgenEksik extends Sekil {
// alanHesapla() implemente edilmedi!
}
void main() {
UcgenEksik u = UcgenEksik(); // ❌ HATA! soyut metod implemente edilmedi
}Bu, derleme zamanında yakalanan bir hatadır — Dart, soyut bir metodun her alt sınıfta gerçekten implemente edildiğinden emin olmanı zorunlu kılar. Bu, "her Sekil'in kesinlikle bir alanHesapla() davranışı olacak" garantisini sağlar.
Soyut Sınıf ile Normal Kalıtım Arasındaki Fark
| Özellik | Normal Class | Abstract Class |
|---|---|---|
| Doğrudan nesne oluşturulabilir mi? | ✅ Evet | ❌ Hayır |
| Soyut (gövdesiz) metod içerebilir mi? | ❌ Hayır | ✅ Evet |
| Somut (gövdeli) metod içerebilir mi? | ✅ Evet | ✅ Evet |
| Alt sınıflar soyut metodları implemente etmek zorunda mı? | — | ✅ Evet |
Neden Soyut Sınıf Kullanılır?
Ana amaç: bir "sözleşme" (contract) tanımlamak. "Her Sekil'in bir alanHesapla() metodu olacak" demek, alt sınıflara bir zorunluluk yüklüyor — bu sayede, Sekil tipindeki herhangi bir nesneyle çalışan kod (Bölüm 7 Konu 33'teki polymorphism örneğini hatırla), her zaman güvenle alanHesapla()'yı çağırabileceğini bilir; çünkü Dart, her alt sınıfın bunu implemente ettiğini derleme zamanında garanti eder.
double toplamAlan(List<Sekil> sekiller) {
double toplam = 0;
for (var sekil in sekiller) {
toplam += sekil.alanHesapla(); // güvenle çağrılabilir, her Sekil'de KESİNLİKLE var
}
return toplam;
}
void main() {
List<Sekil> sekiller = [Daire(3), Kare(4), Daire(2)];
print(toplamAlan(sekiller)); // hepsinin alanı toplanır
}Soyut Sınıfta Constructor Olabilir mi?
abstract class Calisan {
String isim;
Calisan(this.isim); // soyut sınıfın constructor'ı olabilir!
double maasHesapla(); // soyut metod
}
class TamZamanli extends Calisan {
TamZamanli(String isim) : super(isim);
@override
double maasHesapla() => 10000;
}
void main() {
TamZamanli t = TamZamanli("Ahmet");
print("${t.isim}: ${t.maasHesapla()}"); // Ahmet: 10000.0
}Evet, soyut bir sınıfın constructor'ı olabilir — ama bu constructor doğrudan çağrılamaz (Calisan("Ahmet") yazamazsın), sadece alt sınıfların super(...) ile çağırması için vardır. Bu, Bölüm 7 Konu 32'de öğrendiğimiz super mekanizmasının soyut sınıflarla birlikte nasıl çalıştığını gösteriyor.
Soyut Sınıf İçinde Alan Tanımlama
abstract class Arac {
String marka; // soyut sınıfta normal alan tanımlanabilir
Arac(this.marka);
int maksimumHiz(); // soyut metod
void bilgiYazdir() {
print("$marka - Maksimum hız: ${maksimumHiz()} km/s");
}
}
class SporAraba extends Arac {
SporAraba(String marka) : super(marka);
@override
int maksimumHiz() => 300;
}
void main() {
SporAraba araba = SporAraba("Ferrari");
araba.bilgiYazdir(); // Ferrari - Maksimum hız: 300 km/s
}🎯 Bu Dersten Çıkarılması Gerekenler
abstract class, doğrudan nesne oluşturulamayan, sadece diğer sınıfların türemesi için var olan bir sınıftır.- Soyut metod (gövdesiz, sadece imza), her alt sınıfta zorunlu olarak implemente edilmelidir — bu derleme zamanında kontrol edilir.
- Soyut sınıflar hem soyut hem somut metod içerebilir; somut metodlar soyut metodları çağırabilir.
- Soyut sınıfın amacı, alt sınıflar için bir "sözleşme" (contract) tanımlamaktır — bu, polymorphism ile güvenle çalışmayı sağlar.
- Soyut sınıfın constructor'ı olabilir ama sadece alt sınıflar tarafından
super(...)ile çağrılabilir, doğrudan çağrılamaz.
📝 Ödevler
- [ ]
abstract class Hayvanyaz, soyut birsesCikar()metodu tanımla;KediveKopekalt sınıflarıyla implemente et. - [ ] Soyut sınıftan doğrudan nesne oluşturmayı dene (
Hayvan()), hatayı gözlemle. - [ ] Bir alt sınıfta bilerek soyut metodu implemente etme, hatayı gözlemle; sonra implemente edip düzelt.
- [ ] Soyut sınıfa hem soyut hem somut bir metod ekle (somut metod, soyut metodu çağırsın), en az iki alt sınıfla test et.
- [ ]
List<SoyutSinifTipi>alan ve her elemanın soyut metodunu çağıran bir fonksiyon yaz (polymorphism ile), en az 2 farklı alt sınıfla test et.
Sıradaki konu: Bölüm 7 — Konu 35: Interface Mantığı (implements)