Sealed 클래스 (Java 17+)
Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 87개 중 52번째.
기존 Java에서는 클래스를 만들면 (해당 클래스를 final로 표시하지 않는 한) 다른 어떤 클래스든 그 클래스를 상속할 수 있습니다. 하지만 상속은 허용하되 누구나 상속할 수 있도록 하고 싶지는 않다면 어떻게 해야 할까요? Java 17에서는 어떤 클래스가 여러분의 클래스를 상속할 수 있는지 정확하게 제어할 수 있도록 봉인 클래스를 도입했습니다.
sealed class는 sealed 및 permits 키워드를 사용하여 허용되는 하위 class를 명시적으로 선언합니다:
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; }
}Circle, Rectangle, Triangle만 Shape을 확장할 수 있습니다. 이를 확장하려는 다른 class는 컴파일 오류를 발생시킵니다.
허용된 각 하위 클래스는 세 가지 수정자 중 하나를 사용해야 합니다: final(추가 확장 불가), sealed(제한 체인을 계속함) 또는 non-sealed(제한 없는 확장을 허용함):
sealed class Vehicle permits Car, Truck { }
final class Car extends Vehicle { } // 확장할 수 없음
non-sealed class Truck extends Vehicle { } // 누구나 Truck을 확장할 수 있음Sealed classes는 switch 표현식의 패턴 매칭과 함께 사용할 때 특히 강력합니다. 컴파일러가 가능한 모든 하위 타입을 알고 있어 완전성을 검증할 수 있기 때문입니다. 결제 수단, 응답 유형 또는 기하학적 도형처럼 도메인에서 고정된 타입 집합을 모델링할 때 이상적입니다.
챌린지
쉬움애플리케이션에 존재할 수 있는 알림 유형을 제한하여 sealed classes를 보여 주는 알림 시스템을 만들어 보겠습니다. 특정 알림 유형만 허용되는 계층 구조를 만들고, 각 유형이 서로 다른 방식으로 전송을 처리하도록 합니다.
코드를 네 개의 파일로 구성합니다:
Notification.java: 모든 알림의 base 역할을 하는 sealed abstract class를 만드세요. 정확히 세 개의 하위 클래스인EmailNotification,SMSNotification,PushNotification만 허용해야 합니다. sealed class에는 protected fieldmessage(String), 이를 initialize하는 constructor, message의 getter, 그리고 알림이 어떻게 전송되는지를 설명하는 String을 반환하는 abstract methoddeliver()가 필요합니다.EmailNotification.java: Notification을 extends하는finalclass를 만드세요. EmailNotification에는 이메일 주소를 위한 추가 private fieldrecipient(String)가 있습니다. constructor는 message와 recipient를 모두 받아야 하며,super()를 사용하여 parent constructor를 호출해야 합니다.deliver()method는 다음을 반환해야 합니다:Sending email to [recipient]: [message]SMSNotification.java: Notification을 extends하는non-sealedclass를 만드세요. 이렇게 하면 향후 필요한 경우 다른 class가 이를 extends할 수 있습니다. SMSNotification에는 추가 private fieldphoneNumber(String)가 있습니다. constructor는 message와 전화번호를 받습니다.deliver()method는 다음을 반환해야 합니다:Sending SMS to [phoneNumber]: [message]PushNotification.java: Notification을 extends하는finalclass를 만드세요. PushNotification에는 추가 private fielddeviceId(String)가 있습니다. constructor는 message와 device ID를 받습니다.deliver()method는 다음을 반환해야 합니다:Sending push to device [deviceId]: [message]Main.java: 알림 시스템을 하나로 연결하세요! 네 개의 입력을 받습니다: message (String), 이메일 주소 (String), 전화번호 (String), device ID (String).동일한 message와 각각의 contact information을 사용하여 각 notification type을 하나씩 만드세요. 세 개 모두를
Notification[]type의 array에 저장하여 sealed classes를 사용한 polymorphism을 보여 주세요. 그런 다음 array를 Iterate하면서 각 notification에서deliver()를 호출한 결과를 출력하세요.
입력은 다음 순서로 네 개를 받습니다: message, 이메일 주소, 전화번호, device ID.
sealed class가 hierarchy를 어떻게 제한하는지 확인하세요. 허용된 세 개의 class만 Notification을 extends할 수 있습니다. 각 하위 class는 자신을 final, sealed 또는 non-sealed로 선언해야 합니다. 이를 통해 polymorphism을 계속 사용할 수 있으면서도 type hierarchy를 완전히 제어할 수 있습니다!
직접 해보기
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 네 개의 입력을 읽습니다
String message = scanner.nextLine();
String email = scanner.nextLine();
String phoneNumber = scanner.nextLine();
String deviceId = scanner.nextLine();
// TODO: 동일한 메시지를 사용하여 각 알림 유형을 하나씩 생성합니다
// - message와 email을 사용하는 EmailNotification
// - message와 phoneNumber를 사용하는 SMSNotification
// - message와 deviceId를 사용하는 PushNotification
// TODO: 세 개의 알림을 모두 Notification[] 배열에 저장합니다
// 이는 sealed 클래스를 사용한 다형성을 보여줍니다
// TODO: 배열을 순회하며 deliver()의 결과를 출력합니다
// 각 알림에 대해
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
4상속
상속의 기초 (extends)super 키워드메서드 오버라이딩 (@Override)생성자 체이닝Object 클래스단일 및 다중 레벨 상속다중 클래스 상속이 불가능한 이유요약 - 직원 계층 구조직접 연습해 보세요: 온라인 Java 컴파일러