JEP 360: Sealed Types (Preview)

Sealed Types (Preview)

Summary

Sealed Types 으로 Java 프로그래밍 언어를 향상 시키십시오. Sealed Types은 다른 클래스 또는 인터페이스가이를
확장하거나 구현할 수있는 제한을 부과하는 클래스 또는 인터페이스입니다.

Motivation

Java의 유형 시스템을 사용하면 “원은 일종의 모양입니까?”와 같은 질문에 대답 할 수 있지만 “모양의 모양은 무엇입니까?”와 같은 질문에 대한 도움이 크게 줄어 듭니다.
타입 시스템은 어떤 클래스가 라이브러리 타입을 구현할 수 있는지를 제한하는 라이브러리에 대해서는 전혀 도움이되지 않습니다.
즉, 라이브러리 작성자의 설계 의도가 주어진 유형에 특정 하위 유형 세트 만있는 경우에도 적용 할 수 없으므로 구현으로 가정 할 수 없습니다.
(액세스 제어를 사용하면 라이브러리 작성자는 라이브러리에 액세스 할 수있는 패키지를 제한 할 수 있지만 구현 자와 사용자를 구별 할 수는 없습니다.)

유형 시스템에서 “모양은 원 또는 사각형”과 같은 문장을 캡처 할 수 있으므로 사용자에게 유용한 문서를 제공 할뿐만 아니라
Java 컴파일러가 알려진 하위 유형을 철저하게 열거 할 수 있기 때문에 더 나은 유형 검사를 수행 할 수 있습니다.
또한 라이브러리 작성자는 알려진 구현의 동작을 동일한 유지 보수 도메인으로 제한 할 수 있으므로 알려진 구현의 동작을보다 확실하게 추론 할 수 있습니다.

봉인 된 유형은 패턴 일치를 위한 유용한 정보를 제공합니다. 봉인 된 유형과 레코드 는 함께 대수 데이터 유형 이라고하는 구성을 형성합니다 .

Goals

클래스와 인터페이스가 허용 된 하위 유형을 유형 자체와 동일한 유지 보수 도메인에서 열거 된 유형 세트로 제한 할 수있게합니다.

Non-Goals

“친구”와 같은 새로운 형태의 액세스 제어를 제공하거나 멤버 재정의에 대한 세밀한 제어를 제공하는 것은 목표가 아닙니다.

Description

밀봉 유형은 하위 유형이 유형의 선언으로 지정된 지침에 따라 제한되는 것입니다.
하위 유형 지정이 완전히 금지 된 경우 인라인은 강력한 형태의 씰링으로 간주 될 수 있습니다.

실링은 두 가지 목적으로 사용됩니다.
첫 번째는 봉인 클래스의 하위 클래스가 될 수있는 클래스를 제한한다는 것입니다.
두 번째는 밀봉 된 유형의 인스턴스에 대한 유형 패턴을 전환 할 때와 같이 사용 현장에서 철저한 분석 을 가능 하게 한다는 것 입니다.

sealed 선택적 permits절을 사용 하여 수정자를 클래스 또는 인터페이스 에 적용하여 클래스가 봉인되도록 지정합니다 .

1
2
3
sealed interface Node
permits A, B, C { ... }

명시 적 permits절을 사용하면 절에 Node열거 된 유형에 의해서만 확장 될 수 있으며,
동일한 모듈의 멤버이거나 이름이없는 모듈의 경우 동일한 패키지의 멤버 여야합니다.

많은 상황에서 이것은 지나치게 명시적일 수 있습니다.
모든 하위 유형이 동일한 컴파일 단위로 선언되면 permits절을 생략 할 수 있습니다.
이 경우 컴파일러는 permits동일한 컴파일 단위로 선언 된 하위 유형을 열거하여 절을 유추합니다.

봉인 된 유형의 익명 서브 클래스 (및 람다)는 금지됩니다.

봉인 된 유형의 추상 하위 유형은 non-sealed수정 자로 선언하지 않는 한 암시 적으로 봉인 됩니다.

봉인 된 유형의 콘크리트 하위 유형은 non-sealed수정 자 와 함께 선언하지 않는 한 암시 적으로 최종적 입니다.

최종 성과 마찬가지로 씰링은 언어 컴파일러와 JVM 모두에 의해 시행됩니다.
유형의 봉인과 허용되는 하위 유형 목록은 class파일에서 수정되어 런타임에 적용됩니다.

Grammar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
NormalClassDeclaration:
{ClassModifier} class TypeIdentifier [TypeParameters]
[Superclass] [Superinterfaces] [PermittedSubclasses] ClassBody

ClassModifier:
(one of)
Annotation public protected private
abstract static sealed final non-sealed strictfp

PermittedSubclasses:
permits ClassTypeList

ClassTypeList:
ClassType {, ClassType}

Restrictions

  • non-sealed수퍼 타입이 봉인되지 않은 경우 수정자가 유형에 표시 되면 오류 입니다.
  • 그것은 오류가 하나 이상있는 경우 final, sealed또는 non-sealed모든 종류의 선언에 나타납니다.
  • permits절이 선언되지 않은 유형에 나타나는 경우 오류 sealed입니다.

Compiled form of a sealed type

class봉인 된 유형 의 파일 Permitted Subtypes에는 허용 된 하위 유형을 열거 하는 속성이 있어야합니다.
소스 코드에서 봉인 된 유형의 선언에 명시적인 permits절이 없으면 컴파일 된 시간에 허용 된 하위 유형 세트가 봉인 된 유형과 동일한 컴파일 단위로 선언 된 봉인 된 유형의 하위 유형이되도록 계산됩니다.

1
2
3
4
5
6
7
PermittedSubtypes_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 permitted_subtypes_count;
u2 classes[permitted_subtypes_count];
}

Reflection API

다음과 같은 공개 방법이 추가됩니다 java.lang.Class.

  • java.lang.constant.ClassDesc<?>[] getPermittedSubtypes()
  • boolean isSealed()

메소드 getPermittedSubtypes() 반환 포함한 배열 java.lang.constant.ClassDesc 모든이가 봉인되어있는 경우,
이 클래스의 서브 타입을 허용하고,이 클래스가 봉인되지 않은 경우는 하늘의 배열을 반환 나타내는 개체를.

방법은 isSealed 지정된 클래스 또는 인터페이스가 봉인되어있는 경우 true를 반환합니다. (isEnum 와 비교하십시오 .)

Alternatives

일부 언어는 Haskell의 기능 과 같은 대수 데이터 형식 을 직접 지원 data합니다.
enum 제품의 합계를 단일 선언으로 정의 할 수있는 기능 의 변형을 통해 Java 개발자에게 친숙한 방식으로 ADT를보다 직접적으로 표현할 수 있습니다.
그러나 이는 둘 이상의 컴파일 단위에서 클래스에 대한 합계의 범위 나 제품이 아닌 클래스에 대한 합계의 경우와 같이 원하는 사용 사례를 모두 지원하지는 않습니다.

이 permits기능을 사용하면 Node앞에서 설명한 인터페이스 와 같은 봉인 된 유형 을 모든 모듈의 코드로 호출 할 수 있지만 봉인 된 유형의 모듈에서만 코드를 통해 액세스 할 수 있습니다.
이것은 타입 시스템을 액세스 제어 시스템보다 더 표현력있게 만듭니다.
액세스 제어만으로 Node어떤 패키지의 코드로도 호출 할 수있는 경우 (패키지를 내보내므로) Node모든 모듈에서 구현하기 위해 액세스 할 수도 있습니다.
Node다른 모듈에서 구현할 수없는 경우 다른 모듈 Node에서도 호출 할 수 없습니다.

Dependencies

봉인 된 유형은 레코드 (JEP 359) 와 잘 어울리 므로 패턴 일치에 자연스럽게 적용됩니다.
스위치의 패턴이 유형 패턴 또는 전체 분해 패턴 일 때 밀봉 정보를 사용하여 유형이 봉인 된 대상의 스위치 오버를 철저하게 검사 할 수 있습니다.

참조