성장기록지

코틀린 sealed class와 실제 활용 예시 본문

코틀린

코틀린 sealed class와 실제 활용 예시

pengcon 2025. 1. 4. 16:07

Sealed class의 기능적 특징

sealed 클래스는 자기 자신이 추상 클래스이고, 자신을 상속받는 여러 서브 클래스들을 가질 수 있다.

enum 클래스와 달리 상속을 지원하기 때문에, 상속을 활용한 풍부한 동작을 구현할 수 있다.

제일 중요한 것은, 자신을 상속받는 서브 클래스의 종류를 제한할 수 있다.

어떻게 자신을 상속받는 서브클래스를 제한할 수 있을까? 
우선, sealed 클래스의 서브 클래스들은 반드시 같은 패키지 내에 선언되어야 한다.
(sealed 클래스의 서브 클래스를 상속한 클래스들은 같은 패키지 내에 없어도 된다.)
또한 sealed 클래스는 기본적으로 abstract 클래스이고,
sealed 클래스는 private 생성자만 갖게 되기 때문이다.

다른 패키지에 선언했을 때 이렇게 뜬다

Sealed class의 등장 배경

그렇다면 왜 sealed class가 등장하게 되었을까? 

아래 예제 추상 클래스의 예제 코드를 확인 해보자.

컴파일러가 else 브랜치를 추가하라고 오류를 내보낸다.

왜 그럴까? 이는 컴파일러가 PenguinState를 상속 받는 하위 클래스의 종류를 알지 못해 그렇다. 

종류를 알지 못하기에, 아래와 같이 Idle 상태를 없어도 컴파일에서 아무런 오류가 나지 않는다.

이렇게 된다면 당연히 Idle에 대한 처리가 되지 않기 때문에, 많은 오류를 야기할 수 있다.

 

이를 해결하기 위해 상속 받는 자식 클래스(child class)의 종류를 제한하는 특성을 가진 sealed class가 나오게 되었다.

아래와 같이 sealed class로 펭귄의 상태를 바꿔주었을 때, Idle 브랜치나 else가 꼭 필요하다고 컴파일러가 오류를 뱉는다.

 

이렇게 하면 많은 오류를 제한할 수 있고, 상속받는 클래스들을 쉽게 관리할 수 있을 것이다.

sealed class의 또 하나의 특징으로 상속 클래스가 쉽게 관리되는데,

위에서도 말했지만 서브 클래스들이 반드시 같은 파일 내에 선언되어야 하기 때문이다!

이를 통해 컴파일러가 모든 패키지를 돌면서 자식을 찾는 것을 방지해 성능을 높일 수 있다.

 

 

sealed class 상속시 주의할 점

sealed class를 class로 상속받으면 다음과 같은 경고가 뜬다.

상태(변수)가 있거나 equals를 override할 경우에만 class로 상속 받으라는 이야기이다. 

그 이외에는 메모리 절약을 위해 object를 이용한다.

object는 싱글톤 패턴으로 한 번만 메모리에 올라가고 재사용되기 때문이다. 

 

코틀린 1.9버전부터는 data object를 활용할 수 있게 되었다.

data object는 컴파일 시점에 toString, hashCode, equals 함수가 재정의 된다. 

자세한건 data object 블로그 글을 통해 작성하겠다.

결론적으로, data object를 상속받게 하면 경고가 사라지게 된다.

실제 프로젝트 활용 예시

아래와 같이 퀴즈의 타입을 (실시간, 일반) 확인할 때 sealed class를 활용하였다.

컴파일 타임에 정의해둔 타입들을 한 파일 안에서 안전하게 다루기 위해 아래와 같이 구현하였다.

학습 후에 자가적인 피드백을 해보았을 때,

하지만 서버의 배포에 따라 realTime과 general 외에도 다른 값을 줄 수 있기에 else 블럭을 만들었는데,

이렇다면 sealed class의 특징이 사라지므로 abstract class나 data class로 해도 되지 않았을까 라는 생각이 들긴 했다