728x90
오늘은 Java 17에서 정식으로 도입된 '봉인 클래스(Sealed Classes)'에 대해 알아보겠습니다. 이 기능은 객체지향 프로그래밍의 상속 구조를 더욱 효과적으로 제어할 수 있게 해주는 흥미로운 기능입니다.
봉인 클래스란 무엇인가?
봉인 클래스는 클래스 계층 구조를 명시적으로 제한할 수 있게 해주는 Java 17의 새로운 기능입니다. 간단히 말해, 어떤 클래스가 자신을 상속받을 수 있는 하위 클래스들을 제한할 수 있게 해줍니다.
기존 Java에서는 클래스를 final로 선언하여 상속을 완전히 막거나, 아무런 제한 없이 누구나 상속할 수 있게 하는 두 가지 극단적인 선택지만 있었습니다. 봉인 클래스는 이 두 가지 사이의 중간 지점을 제공합니다.
봉인 클래스의 기본 문법
봉인 클래스를 정의하는 기본 문법은 다음과 같습니다:
// 부모 클래스를 sealed로 선언하고 permits 키워드로 허용할 하위 클래스 명시
public sealed class Shape permits Circle, Rectangle, Triangle {
// 클래스 내용
}
// 허용된 하위 클래스들은 final, sealed, non-sealed 중 하나로 선언해야 함
public final class Circle extends Shape {
// final: 더 이상 상속 불가
}
public sealed class Rectangle extends Shape permits Square {
// sealed: 제한된 상속 허용
}
public non-sealed class Triangle extends Shape {
// non-sealed: 제한 없이 상속 허용
}
// Rectangle의 하위 클래스로 허용된 Square
public final class Square extends Rectangle {
// 내용
}
봉인 클래스의 주요 특징
- 명시적 상속 제어: permits 키워드를 사용하여 상속 가능한 하위 클래스를 명시적으로 나열합니다.
- 하위 클래스 선언 의무: 봉인 클래스를 상속받는 모든 클래스는 다음 세 가지 중 하나로 선언되어야 합니다:
- final: 더 이상 상속할 수 없음
- sealed: 제한된 상속만 허용
- non-sealed: 제한 없이 상속 허용
- 같은 모듈 또는 패키지 내 존재: 기본적으로 봉인 클래스와 그 허용된 하위 클래스들은 동일한 모듈(또는 모듈이 없는 경우 동일 패키지) 내에 있어야 합니다.
봉인 클래스의 실용적 사용 예시
예시 1: 결제 시스템 구현
public sealed abstract class Payment permits CreditCard, DebitCard, BankTransfer, DigitalWallet {
protected double amount;
public abstract boolean processPayment();
}
public final class CreditCard extends Payment {
private String cardNumber;
private String expiryDate;
@Override
public boolean processPayment() {
// 신용카드 결제 처리 로직
return true;
}
}
public final class DebitCard extends Payment {
private String cardNumber;
private String pin;
@Override
public boolean processPayment() {
// 직불카드 결제 처리 로직
return true;
}
}
public final class BankTransfer extends Payment {
private String accountNumber;
@Override
public boolean processPayment() {
// 계좌이체 처리 로직
return true;
}
}
public non-sealed class DigitalWallet extends Payment {
private String walletId;
@Override
public boolean processPayment() {
// 디지털 지갑 결제 처리 로직
return true;
}
}
예시 2: 패턴 매칭과의 조합
Java 17에서는 봉인 클래스가 패턴 매칭과 함께 사용될 때 그 진가를 발휘합니다:
public sealed interface Shape permits Circle, Rectangle, Triangle {
double area();
}
public final record Circle(double radius) implements Shape {
@Override
public double area() {
return Math.PI * radius * radius;
}
}
public final record Rectangle(double width, double height) implements Shape {
@Override
public double area() {
return width * height;
}
}
public final record Triangle(double base, double height) implements Shape {
@Override
public double area() {
return 0.5 * base * height;
}
}
// 패턴 매칭을 활용한 처리
public void printArea(Shape shape) {
double area = switch (shape) {
case Circle c -> c.area();
case Rectangle r -> r.area();
case Triangle t -> t.area();
// Shape이 봉인되어 있으므로 default 케이스가 필요 없음!
};
System.out.println("도형의 면적: " + area);
}
봉인 클래스의 장점
- 타입 안전성 향상: 클래스 계층 구조를 명확하게 정의하고 제한함으로써 타입 안전성이 향상됩니다.
- 패턴 매칭 최적화: 패턴 매칭에서 가능한 모든 케이스가 명시적으로 정의되므로, 컴파일러가 망라성(exhaustiveness) 검사를 수행할 수 있습니다.
- API 설계 명확화: 라이브러리 개발자가 의도한 상속 구조를 명확하게 표현할 수 있습니다.
- 유지보수성 개선: 클래스 계층 구조가 명확하게 정의되어 있어 코드 이해와 유지보수가 쉬워집니다.
실무에서의 적용 사례
봉인 클래스는 다음과 같은 상황에서 특히 유용합니다:
- 도메인 모델링: 비즈니스 개념이 명확하게 제한된 유형 집합으로 모델링될 때 (예: 주문 상태, 결제 방법 등)
- 라이브러리/프레임워크 설계: 확장 지점을 명확하게 정의해야 할 때
- 패턴 매칭 활용: switch 표현식이나 패턴 매칭을 활용한 로직 처리 시
- 컴파일러 최적화: 컴파일러가 클래스 계층에 대해 더 많은 가정을 할 수 있게 함으로써 최적화 기회를 제공
주의사항
- 모듈/패키지 제약: 봉인 클래스와 그 허용된 하위 클래스들은 기본적으로 같은 모듈이나 패키지 내에 있어야 합니다.
- 하위 클래스 제약: 모든 하위 클래스는 final, sealed, 또는 non-sealed로 선언되어야 합니다.
- IDE 지원: 최신 IDE를 사용하여 봉인 클래스 관련 기능을 충분히 활용하세요.
LIST
'Develop > JAVA' 카테고리의 다른 글
Spring Interceptor를 활용한 페이지 이동 추적 및 제어 (1) | 2025.03.26 |
---|---|
[Java] 엑셀파일 읽어서 값 수정 후 다시 엑셀 다운로드 (0) | 2025.02.21 |
[Java] 특정 달의 마지막 날짜와 요일 구하기 (2) | 2025.02.19 |
Spring Framework의 @Scheduled 어노테이션 완벽 가이드 (1) | 2025.02.14 |
[Java] REST API 호출 및 JSON 데이터를 DTO로 파싱하는 방법 (3) | 2025.01.08 |