Menu
Coddy logo textTech

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, başka herhangi bir sınıf onu genişletebilir (final olarak işaretlemediğiniz sürece). Peki kalıtıma izin vermek, ancak herkesten izin vermemek istiyorsanız ne olacak? Java 17, hangi sınıfların sizin sınıfınızı genişletebileceği üzerinde hassas denetim sağlaması için mühürlü sınıfları kullanıma sundu.

Bir mühürlü sınıf, izin verilen alt sınıflarını sealed ve permits anahtar sözcüklerini kullanarak 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; }
}

Yalnızca Circle, Rectangle ve Triangle, Shape sınıfını genişletebilir. Bunu genişletmeye çalışan diğer tüm sınıflar derleme hatasına neden olur.

İ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 zinciri devam eder) veya non-sealed (sınırsız genişletmeye izin verir):

sealed class Vehicle permits Car, Truck { }

final class Car extends Vehicle { }           // Genişletilemez
non-sealed class Truck extends Vehicle { }    // Herkes Truck'ı genişletebilir

Sealed sınıflar, derleyici tüm olası alt türleri bildiği ve kapsamlılığı doğrulayabildiği için switch ifadelerindeki desen eşleştirmeyle özellikle güçlüdür. Ödeme yöntemleri, yanıt türleri veya geometrik şekiller gibi bir alandaki sabit tür kümesini modellemek için idealdir.

challenge icon

Görev

Kolay

Uygulamanızda hangi bildirim türlerinin var olabileceğini kısıtlayarak sealed sınıfları gösteren bir bildirim sistemi oluşturalım. Yalnızca belirli bildirim türlerine izin verilen bir hiyerarşi oluşturacak ve her türün teslimatı farklı şekilde gerçekleştirmesini sağlayacaksınız.

Kodunuzu dört dosya arasında düzenleyeceksiniz:

  • Notification.java: Tüm bildirimlerin temel sınıfı olarak görev yapan sealed bir abstract sınıf oluşturun. Tam olarak üç alt sınıfa izin vermelidir: EmailNotification, SMSNotification ve PushNotification. Sealed sınıfınızda korumalı bir message alanı (String), bunu başlatacak bir kurucu, mesaj için bir getter ve bildirimin nasıl gönderildiğini açıklayan bir String döndüren abstract bir deliver() metodu bulunmalıdır.
  • EmailNotification.java: Notification sınıfını genişleten final bir sınıf oluşturun. Bir EmailNotification, e-posta adresi için ek bir private recipient alanına (String) sahiptir. Kurucusu hem message hem de recipient parametrelerini almalı ve üst sınıf kurucusunu super() ile çağırmalıdır. deliver() metodu şunu döndürmelidir: Sending email to [recipient]: [message]
  • SMSNotification.java: Notification sınıfını genişleten non-sealed bir sınıf oluşturun. Bu, gelecekte gerekirse diğer sınıfların bu sınıfı genişletmesine olanak tanır. Bir SMSNotification, ek bir private phoneNumber alanına (String) sahiptir. Kurucusu message ve telefon numarasını alır. deliver() metodu şunu döndürmelidir: Sending SMS to [phoneNumber]: [message]
  • PushNotification.java: Notification sınıfını genişleten final bir sınıf oluşturun. Bir PushNotification, ek bir private deviceId alanına (String) sahiptir. Kurucusu message ve cihaz kimliğini alır. deliver() metodu şunu döndürmelidir: Sending push to device [deviceId]: [message]
  • Main.java: Bildirim sisteminizi bir araya getirin! Dört girdi alacaksınız: bir message (String), bir e-posta adresi (String), bir telefon numarası (String) ve bir cihaz kimliği (String).

    Aynı message değerini, ancak ilgili iletişim bilgilerini kullanarak her bildirim türünden bir tane oluşturun. Sealed sınıflarla çok biçimliliği göstermek için üçünü de Notification[] türünde bir dizide saklayın. Ardından dizi üzerinde yineleme yaparak her bildirim için deliver() çağrısının sonucunu yazdırın.

Dört girdiyi şu sırayla alacaksınız: message, e-posta adresi, telefon numarası ve cihaz kimliği.

Sealed 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, çok biçimliliği etkinleştirirken tür 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 girdiyi 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 bir tane oluştur
        // - message ve email ile EmailNotification
        // - message ve phoneNumber ile SMSNotification
        // - message ve deviceId ile PushNotification
        
        // TODO: Üç bildirimin tümünü bir Notification[] dizisinde sakla
        // Bu, sealed sınıflarla polimorfizmi gösterir
        
        // TODO: Diziyi dolaş ve deliver() sonucunu yazdır
        // her bildirim için
        
    }
}
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

Kendi başına pratik yap: Online Java derleyicisi