Sealed Class와 Sealed Interface

hongbeom
hongbeomi dev
Published in
4 min readMar 9, 2022

sealed class와 sealed interface에 대해 알아봅니다.

Photo by Jeremy Bishop on Unsplash

우리는 개발을 하며 종종 제한된 일들의 집합이 필요한 경우가 생기게 됩니다. 웹 요청의 성공이나 실패 혹은 유저의 종류 등등..

이를 모델로 구현하기 위해 enum을 사용할 수도 있지만, enum 클래스는 각각 값의 단일 인스턴스만 허용하고, 타입에 대한 개별의 정보를 표현할 수 없습니다. 물론 추상 클래스와 여러가지 익스텐션을 사용하여 해결할 수도 있겠지만 이 경우엔 enum에서 가져온 제한된 타입의 장점을 얻을 수 없게 됩니다.

이 단점들을 커버할 수 있는 클래스가 바로 Sealed 클래스입니다.

🔰 Sealed Class

실드 클래스는 추상 클래스처럼 계층을 나타낼 수 있으며 하위 클래스는 데이터 클래스, Object, 일반 클래스, 또 다른 실드 클래스 등 모든 타입의 클래스가 될 수 있습니다.

위 코드는 Android에서 흔하게 볼 수 있는 UI 상태를 관리하는 실드 클래스입니다. 자식 클래스는 상위 클래스인 UiState 클래스를 상속 받음으로서 계층구조를 표현할 수 있습니다.

물론 하위 클래스로 또 다른 실드 클래스를 선언하여 그 안에서 새로운 계층을 구현할 수 도 있습니다. 또한 실드 클래스의 모든 하위 타입이 모두 알려져 있으므로, IDE가 모든 분기점을 인식할 수 있게 됩니다.

내부 동작

그렇다면 실드 클래스는 내부적으로 어떻게 동작하는 것일까요? 변환된 자바 파일을 살펴봅시다.

코드가 상당히 길어지는데, UiState 클래스는 추상클래스로 바뀌었고, @Metadata 어노테이션에 해당 클래스의 정보, 하위 클래스 정보가 들어있어서 컴파일러가 이를 인지하게 됩니다. 또 private 생성자가 생겼으며, 컴파일러가 접근할 수 있는 synthetic 생성자가 만들어졌습니다. 따라서 이 클래스는 다른 어떤 클래스에서도 직접적으로 생성할 수 없다는 것을 의미합니다.

하위 클래스에도 메타데이터 어노테이션이 붙어있어 이를 컴파일러가 인지하게 됨을 알 수 있습니다.

⚜️ Sealed Interface

Kotlin 1.5 미만 버전에서는 Sealed 클래스는 최상위 클래스가 인터페이스가 될 수 없었으며, 모든 하위 클래스는 동일한 파일에 존재해야 했습니다.

하지만 Kotlin 1.5 버전에서 Sealed 인터페이스가 추가되며, 두 가지 제약 조건을 모두 제거되었습니다. Sealed 인터페이스를 구현하는 하위 클래스 및 인터페이스는 다른 파일(단, 같은 모듈에 있어야 함)에 있어도 상관이 없으며(Sealed 클래스도 마찬가지), 라이브러리 외부에서 상속과 구현을 위해 인터페이스를 닫을 때 유용하게 사용할 수 있습니다.

인터페이스를 Sealed로 정의하면, 해당하는 구현이 동일한 컴파일 유닛 및 패키지로 제한되므로 라이브러리의 경우 라이브러리 외부에서 이를 구현할 수 없게 됩니다.

실드 인터페이스를 사용하는 것은 코틀린에서 허용되지 않는 클래스 다중 상속으로 인한 실드 클래스의 단점을 보완하는 하나의 방법이 될 수 있습니다.

실드 인터페이스를 사용하는 유용한 예시는 아래 글을 참고해보세요.

내부 동작

마찬가지로 실드 인터페이스의 디컴파일된 자바 파일을 살펴봅시다.

위와 같은 코드로 사용할 때, 자바 파일은 다음과 같이 생성됩니다.

실드 인터페이스는 public 인터페이스로 변경되고, 실드 클래스와 마찬가지로 @Metadata 어노테이션을 통해 컴파일러에게 클래스 계층 구조 정보를 제공해줍니다.

클래스 계층 구조를 모델링 할 때, 실드 클래스 & 실드 인터페이스는 좋은 방법이 될 수 있을 것 같습니다.

읽어주셔서 감사합니다🙌

--

--