본문 바로가기

Kotlin

Kotlin Sealed class

주의

이 블로그는 개인적인 생각과 이해를 정리한 곳입니다. 실제와 다를 수 있으니 글에서 참고한 글을 꼭 확인해주세요.

요약

enum class와 일반 class의 중간 형태. enum 처럼 타입 형을 제한시킬 수 있으면서 class의 성격을 모두 가지고 있다.

Sealed class란?

Seales class는 class의 정해진 하위 클래스만 상속되도록 제한을 한다. enum과 비슷하다고 볼 수 있는데, 선언된 클래스 외에는 상속 받을 수 없기 때문에 if나 when과 같은 조건문에서 예외사항들을 최대한 줄일 수 있다. 예를 들어서 설명하면 이해에 도움이 될 것이다.

Example

sealed class State {
    object Loading : State()
    class Data(val list: List<Any>) : State()
    class Error(val message: String) : State()
}

fun main() {
    val state = createState()
    when (state) {
        is State.Loading -> println("loading...")
        is State.Data -> println("list=${state.list}")
        is State.Error -> println("message=${state.message}")
        // nonNull인 경우 else는 신경쓰지 않아도 된다.
    }
}

fun createState(): State = // create...

 

main() 함수 안에 있는 when 코드 부분을 살펴보면 enum을 사용할 때와 유사한 형태로 조건문을 작성할 수 있다는 것을 확인할 수 있다. 그리고 해당 조건이 true면 실제 클래스의 멤버 변수, 멤버 함수를 Kotlin smart casts 기술로 모두 사용할 수 있다는 것을 확인할 수 있다.

 

State를 Sealed class로 선언하고 이를 상속받는 Class를 Loading, Data, Error로 제한함으로써 when문에서 마치 enum을 사용하는 것 처럼 한정된 클래스들로만 분기할 수 있다. 그리고 Sealed class로 선언됐기 때문에, IDEA(Intellij, Android Studio)에서 불필요한 조건문을 찾아주고 이를 우리에게 알려준다. Class에 의미를 부여하면서 코드 분석이 쉬워진다는 것을 의미한다. 또 Kotlin smart casts의 지원으로 Type casting을 할 필요 없이 직접 멤버 변수와 함수에 접근이 가능하다. 결과적으로 우리는 더욱 더 깔끔한 코드를 작성할 수 있게 된다!

State 예제를 Enum으로 구현한다면?

다음 예제를 보면 구현하는데 어려움이 있다는 것을 쉽게 알 수 있다.

enum class State {
    Loading, Data, Error
}

fun main() {
    val state = createState()
    when (state) {
        State.Loading -> println("loading...")
        State.Data -> println("list=${state.list}") // list를 어디서 가져오지? ㅠㅠ
        State.Error -> println("message=${state.message}") // message는? ㅠㅠ
        // nonNull인 경우 else는 신경쓰지 않아도 된다.
    }
}

fun createState(): State = // create...

State 예제를 abstract class로 구현한다면?

다음 예제를 보면 동일하게 구현할 수 있다는 것을 알 수 있다. 하지만 직접 에디터에 코드를 작성해보면 when의 분기문을 작성할 때 에디터의 도움을 받을 수 있고 없고의 차이가 발생한다.

abstract class State {
    object Loading : State()
    class Data(val list: List<Any>) : State()
    class Error(val message: String) : State()
}

fun main() {
    val state = createState()
    when (state) {
        is State.Loading -> println("loading...")
        is State.Data -> println("list=${state.list}")
        is State.Error -> println("message=${state.message}")
        // nonNull인 경우 else는 신경쓰지 않아도 된다.
    }
}

fun createState(): State = // create...

 

- 에디터에서 도와주는 기능! -

참고

'Kotlin' 카테고리의 다른 글

Kotlin Delegated Properties(by lazy)  (1) 2020.09.10
Kotlin Regex(정규식)  (1) 2020.09.08
Kotlin Sequences  (0) 2020.09.08