Java의 sealed 클래스와 완전한 패턴 매칭

1 hour ago 3

Java 17에 도입된 sealed 클래스는 허용할 하위 타입을 제한해, 컴파일러가 switch에서 모든 경우를 처리했는지 검사할 수 있게 함 모든 경우를 처리하면 default 없이 switch 표현식을 사용할 수 있으며, 빠뜨린 경우가 있으면 컴파일 오류가 발생함 공개 API의 sealed 타입에 새 하위 타입을 추가하면 기존 사용 코드의 컴파일이 깨질 수 있으므로, SemVer를 따른다면 메이저 버전을 올려야 하는 호환성 파괴 변경임 사용 코드를 다시 컴파일하지 않으면 누락된 분기를 컴파일 시점에 발견하지 못하며, 새 타입을 처리할 때 MatchException 이 발생할 수 있음 sealed 타입은 전체를 함께 다시 컴파일하는 컴포넌트 내부 구현에서 더 유용할 수 있으며, 공개 API로 노출하면 모듈 경계를 넘어 런타임에야 드러나는 호환성 문제를 만들 수 있음 sealed 타입과 완전성 검사 Java 17의 sealed 클래스는 인터페이스나 기반 클래스가 허용하는 하위 타입을 명시적으로 제한함 예제의 SealedType 인터페이스 내부에는 이를 구현하는 레코드 TypeA, TypeB가 있음 허용 목록을 명시하지 않으면 내부 클래스들이 허용 하위 타입에 암묵적으로 추가됨 of(String type)은 "A"와 "B"를 해당 레코드로 변환하고, 그 외 입력에는 IllegalArgumentException을 던짐 이 구조는 Haskell이나 ML의 대수적 데이터 타입과 유사하며, Haskell의 data SealedType = TypeA | TypeB에 대응해 이해할 수 있음 sealed 클래스와 enum은 완전성 검사(exhaustiveness checking) 를 가능하게 함 컴파일러가 가능한 경우를 모두 알기 때문에, TypeA와 TypeB를 처리하는 switch 표현식에는 default가 필요 없음 default가 없는 상태에서 한 경우를 빠뜨리면 컴파일 오류가 발생함 TypeC를 추가하면 기존 Main의 switch에 해당 분기가 없어 재컴파일에 실패함 공개 API로 내보낸 sealed 타입에 하위 타입을 추가하는 것은 사용 코드를 깨뜨릴 수 있으며, SemVer를 따른다면 메이저 버전 증가가 필요함 분리 컴파일의 한계와 공개 API 설계 TypeC와 이를 반환하는 "C" 분기를 추가한 뒤 SealedType.java만 다시 컴파일하면, 기존 Main의 누락된 분기를 컴파일 시점에 검사할 기회가 없음...

Read Entire Article