Sealed Classes (Java 17+)
Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 52 / 87.
Geleneksel Java'da, bir sınıf oluşturduğunuzda, onu final olarak işaretlemediğiniz sürece başka herhangi bir sınıf onu genişletebilir. Peki ya kalıtıma izin vermek istiyor ama bunu herkesin yapmasını istemiyorsanız? Java 17, hangi sınıfların sizinkini genişletebileceği üzerinde size kesin kontrol sağlamak için mühürlü sınıfları (sealed classes) tanıttı.
Bir sealed class, `sealed` ve `permits` anahtar kelimelerini kullanarak izin verilen alt sınıflarını açıkça bildirir:
sealed abstract class Shape permits Circle, Rectangle, Triangle {
abstract double area();
}
final class Circle extends Shape {
double radius;
double area() { return Math.PI * radius * radius; }
}
final class Rectangle extends Shape {
double width, height;
double area() { return width * height; }
}
final class Triangle extends Shape {
double base, height;
double area() { return 0.5 * base * height; }
}Sadece Circle, Rectangle ve Triangle, Shape sınıfını genişletebilir. Onu genişletmeye çalışan diğer tüm sınıflar bir derleme hatasına neden olacaktır.
İzin verilen her alt sınıf üç değiştiriciden birini kullanmalıdır: final (daha fazla genişletme yapılamaz), sealed (kısıtlama zincirini devam ettirir) veya non-sealed (kısıtlanmamış genişletmeye açar):
sealed class Vehicle permits Car, Truck { }
final class Car extends Vehicle { } // Genişletilemez
non-sealed class Truck extends Vehicle { } // Herkes Truck sınıfını genişletebilirMühürlü sınıflar (sealed classes), derleyicinin tüm olası alt türleri bilmesi ve kapsamlılığı (exhaustiveness) doğrulayabilmesi sayesinde switch ifadelerindeki desen eşleştirme (pattern matching) ile özellikle güçlüdür. Ödeme yöntemleri, yanıt türleri veya geometrik şekiller gibi bir etki alanındaki sabit bir tür kümesini modellerken idealdirler.
Görev
KolayUygulamanızda hangi bildirim türlerinin var olabileceğini kısıtlayarak mühürlü sınıfları (sealed classes) gösteren bir bildirim sistemi oluşturalım. Sadece belirli bildirim türlerine izin verilen bir hiyerarşi oluşturacaksınız ve her tür, iletimi farklı şekilde gerçekleştirecek.
Kodunuzu dört dosya halinde düzenleyeceksiniz:
Notification.java: Tüm bildirimler için temel teşkil eden mühürlü bir soyut sınıf (sealed abstract class) oluşturun. Tam olarak üç alt sınıfa izin vermelidir:EmailNotification,SMSNotificationvePushNotification. Mühürlü sınıfınızın korumalı birmessage(String) alanına, bunu başlatan bir yapıcıya (constructor), mesaj için bir getter metoduna ve bildirimin nasıl gönderildiğini açıklayan bir String döndüren soyut birdeliver()metoduna ihtiyacı vardır.EmailNotification.java: Notification sınıfını genişleten birfinalsınıf oluşturun. Bir EmailNotification, e-posta adresi için ek bir özelrecipient(String) alanına sahiptir. Yapıcısı hem mesajı hem de alıcıyı almalı vesuper()ile üst sınıf yapıcısını çağırmalıdır.deliver()metodu şu değeri döndürmelidir:"Sending email to " + recipient + ": " + messageSMSNotification.java: Notification sınıfını genişleten birnon-sealedsınıf oluşturun; bu, gelecekte gerekirse diğer sınıfların onu genişletmesine olanak tanır. Bir SMSNotification, ek bir özelphoneNumber(String) alanına sahiptir. Yapıcısı mesajı ve telefon numarasını alır.deliver()metodu şu değeri döndürmelidir:"Sending SMS to " + phoneNumber + ": " + messagePushNotification.java: Notification sınıfını genişleten birfinalsınıf oluşturun. Bir PushNotification, ek bir özeldeviceId(String) alanına sahiptir. Yapıcısı mesajı ve cihaz kimliğini alır.deliver()metodu şu değeri döndürmelidir:"Sending push to device " + deviceId + ": " + messageMain.java: Bildirim sisteminizi bir araya getirin! Dört girdi alacaksınız: bir mesaj (String), bir e-posta adresi (String), bir telefon numarası (String) ve bir cihaz kimliği (String).Aynı mesajı ancak ilgili iletişim bilgilerini kullanarak her bildirim türünden birer tane oluşturun. Mühürlü sınıflarla polimorfizmi (çok biçimlilik) göstermek için her üçünü de
Notification[]tipinde bir dizide saklayın. Ardından dizi boyunca ilerleyin ve her bildirimdedeliver()metodunu çağırmanın sonucunu yazdırın.
Sırasıyla dört girdi alacaksınız: mesaj, e-posta adresi, telefon numarası ve cihaz kimliği.
Mühürlü sınıfın hiyerarşiyi nasıl kısıtladığına dikkat edin; yalnızca izin verilen üç sınıf Notification sınıfını genişletebilir. Her alt sınıf kendisini final, sealed veya non-sealed olarak bildirmelidir. Bu, polimorfizmi etkin kılarken tip hiyerarşiniz üzerinde tam kontrol sahibi olmanızı sağlar!
Kendin dene
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Dört girişi oku
String message = scanner.nextLine();
String email = scanner.nextLine();
String phoneNumber = scanner.nextLine();
String deviceId = scanner.nextLine();
// TODO: Aynı mesajı kullanarak her bildirim türünden birer tane oluşturun
// - message ve email ile EmailNotification
// - message ve phoneNumber ile SMSNotification
// - message ve deviceId ile PushNotification
// TODO: Üç bildirimin tümünü bir Notification[] dizisinde saklayın
// Bu, sealed sınıflar ile polimorfizmi gösterir
// TODO: Dizi üzerinde döngü kurun ve deliver() sonucunu yazdırın
// her bildirim için
}
}
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
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesnelerthis Anahtar KelimesiMetotlarAlanlar (Öznitelikler)Yapıcı MetotYapıcı Metot Aşırı YüklemeÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (extends)super Anahtar KelimesiMetot Geçersiz Kılma (@Override)Yapıcı Metot ZincirlemeObject SınıfıTekli ve Çok Seviyeli KalıtımNeden Çoklu Sınıf Kalıtımı Yok?Özet - Çalışan Hiyerarşisi7Özel Metotlar ve Object Sınıfı
toString() Metoduequals() ve hashCode()clone() MetoducompareTo() ve ComparableComparator ArayüzüÖzet - Özel Sıralama2Erişim Belirleyiciler ve Kapsülleme
Erişim Seviyelerine Genel BakışGetter ve Setter MetotlarıBilgi Gizlemefinal Anahtar KelimesiÖzet - Banka Hesabı Yöneticisi5Polimorfizm
Metot Aşırı Yükleme TemelleriMetot Geçersiz Kılma (Çalışma Zamanı)Upcasting ve Downcastinginstanceof OperatörüSoyut Sınıflar ve MetotlarÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon vs KalıtımAgregasyon vs KompozisyonDahili, Yuvalanmış ve Anonim SınıflarEnum'lar ve Enum MetotlarıRecords (Java 16+)Sealed Classes (Java 17+)11Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıBuilder KalıbıObserver KalıbıStrategy Kalıbı14Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi3Sınıf Özellikleri ve Statik Üyeler
Instance ve Statik DeğişkenlerStatik MetotlarStatik BloklarSabitler (static final)Özet - Sayaç ve Utility6Arayüzler ve Soyut Sınıflar
Arayüzlere GirişArayüzleri UygulamaÇoklu Arayüz UygulamaArayüzlerde Default ve StaticSoyut Sınıflar ve ArayüzlerFonksiyonel ArayüzlerÖzet - Ödeme Sistemi9Generics
Generics'e GirişGeneric SınıflarGeneric MetotlarSınırlandırılmış Tip ParametreleriWildcard'lar (?, extends, super)Özet - Generic Container12Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıYineleyici Kalıbı