본문 바로가기
Android(Kotlin)

[Kotlin] Sealed Class

by 클리마 2024. 2. 23.
728x90

탄생배경


기존 Enum class의 한계

  • 상태 정의는 가능
  • 하지만 상태에 따른 값을 넘겨주거나 넘겨주더라도 동일한 자료형만 넘길 수 있음

기존 Abstract class와 Kotlin when문과의 부적합성

  • Abstract class로 상태들을 하나로 묶어줄 경우 Enum class의 한계를 해결할 수 있음
  • 그러나 Kotlin에서 when문을 사용하여 abstract class의 상태에 따라 분기할 때 compiler의 불안정 발생
    • abstract class만으로 모든 경우를 해결할 수 없고, else -> 분기가 필요로 함

Sealed class의 특징


  • Enum class와 Abstract class로 정의할 때 문제점을 해결한 추상 클래스
  • 추상 클래스이지만 제한된 클래스 계층구조를 가짐
    • 상속된 클래스는 Sealed class와 같은 파일에 있어야 한다.
      => 컴파일러가 부모 클래스를 상속하는 하위 클래스가 어떤 것이 있는지 알도록 함.
  • 추상 클래스이기 때문에 직접 객체 인스턴스 생성이 불가하다.

Sealed class 선언방법


하위 클래스는 주로 data class나 object를 사용

why? -> 메모리의 효율화를 위해!!

=> 일반 class가 sealed class를 상속받으려고 하면 다음과 같은 Warning이 뜬다.

'sealed' subclass has no state and no overriden 'equals()'
상태가 있거나 equals()를 override할 경우에만 class에 상속받으라는 Warning

sealed class Result()

data class Success(val data: String?) : Result()
data class Fail(val message: String?) : Result()
object Error(val exception: Exception) : Result()
sealed class Result {
    data class Success(val data: String?) : Result()
    data class Fail(val message: String?) : Result()
    object Error(val exception: Exception) : Result()
}

그렇다면 Enum은 필요없는 것인가?


공식문서에서는 Sealed class는 Enum의 확장이라고 기술되어 있다.
하지만 우리가 동일한 생성자를 가지고 가는 경우도 많고 Sealed class가 가지고있지 않은 Enum만의 특징이 있기 때문에 둘을 경우에 맞게 쓰는 것이 좋다.

Enum만의 특징

  • iterate가 가능하다.
WeekDays.values()
    .map { "$it은 주중입니다." }
    .forEach { println(it) }

enumValues<WeekDays>()
    .map { "$it은 주중입니다." }
    .forEach { println(it) }
  • 특정 Enum 값만 가져올 수 있다.
    • when 문을 이용하여 모든 Enum을 지정하지 않고 특정 Enum의 값을 가져올 수 있다.
val selected = enumValueOf<WeekDays>("FRIDAY").text
val selected2 = WeekDays.valueOf("FRIDAY").text
728x90