Sealed class가 만들어진 이유

 

하나의 부모 class 안의 여러 자식 class 존재 한다고 했을 때 컴파일러는 부모 class를 상속 받은 자식 class들이 있는지 알지 못한다

 

예를 들어 보면 3개의 상태 종류로 api성공  /  api에러 / network 에러를 다음과 같이 표현 할 수 있다

abstract class NetworkState {
    
    class ApiSuccess : NetworkState()

    class ApiError : NetworkState()

    class NetworkError : NetworkState()

}

class 상속 예제

 

각 state 별로 상태 메시지를 얻고 싶다고 가정했을 때 이를 위해 getStateNetwork함수를 만들어보자

fun getStateMessage(networkState: NetworkState): String {
    return when (networkState) {
        is ApiSuccess -> "ApiSuccess"
        is ApiError -> "ApiError"
        is NetworkError -> "NetworkError"
    }
}

getStateMessage 함수

 

그러면 다음과 같이 else branch를 추가하라는 오류를 만든다

when 오류

왜 else branch를 추가를 해야되냐면 컴파일러가 NetworkState를 상속받는 하위 클래스의 종류를 알지 못하기 때문이다

 

단순해 보이지만 여기서 만약 ApiError에 대한 분기를 지우게 된다면 그러면 다음과 같이 오류 없이 컴파일 되는것을 볼수 있다

 

apiError 분기 지우기

 

만약 위의 코드가 실제로 적용되어 있다면 ApiError에 대한 처리가 되어 있지 않아 문제를 잡아내기가 힘들다

 

NetworkState를 사용하는 부분이 한곳이라면 그나마 다행이지만 대부분은 그렇지 않다.

 

즉 위의 코드는 오류를 내뱉을 수 있고 관리도 되지 않은 코드가 되어버린다.

 

그래서 그것에 대한 대안이 sealed class이다 

sealed class란 추상 클래스로 상속받는 자식 클래스의 종류를 제한하는 특성을 가지고 있다. 즉 컴파일러에서 sealed class의 자식 클래스가 어떤 것 인지 알 수 있다

 

sealed class NetworkState {

    class ApiSuccess : NetworkState()

    class ApiError : NetworkState()

    class NetworkError : NetworkState()

}

seled class 예제

 

다음 그림처럼 오류가 발생하지 않는다 이유는 컴파일러에서 sealed class NetworkState의 자식 클래스 ApiSuccess , ApiError , NetworkError 세가지만 알고 있기 때문이다 즉 when에서 else branch를 사용하지 않고도 필요한 메시지만 수신할 수 있게 된다

 

sealed class를 이용한 getStateMessage

 

여기서 앱을 확장해서 NetworkState에 UnknownError를 추가한다고 했을때 어떤 일이 일어나는지 알아보자

이때 컴파일러는 오류를 발생 시킨다 sealed class인 UnknownError에 대한 처리가 안되어 있기 때문이다.

sealed class를 상속 받은 것에 대한 처리가 없을 경우

 

하지만 위의 그림에서 약간의 이상함을 느꼇을 것이다 왜 상속받은 class들은 주의 표시가 되어 있을까?

 

sealed class 상속 warning

 

해석 : sealed class의 subclass 상태가 없고 equals()를 오버라이드 하지도 않는다

 

즉 상태(변수)가 있거나 equals를 override 할 경우에만 class로 상속받으라는 말이다 그 이외에는 메모리 절약을 위해 object를 이용한다

 

위의 코드를 다음과 같이 변경하게 되면 warning이 사라진다. 

 

object로 상속받기

 

object는 싱글톤 패턴으로 한번만 메모리에 올라가고 재사용된다 따라서 상태가 없는 경우 객체를 두 번 이상 생성하여 메모리에 올리는 것은 메모리를 낭비하는 것이다. 따라서 object로 바꿀 경우 warning이 사라지게 된다.

 

 

Sealed class의 특징

 

같은 패키지의 자식 클래스만 상속 가능

컴파일러가 모든 패키지를 돌면서 자식을 찾는 것은 리소스를 많이 소모하는 작업이다 따라서 sealed class는 자식 클래스에 대한 선언을 같은 패키지 내로 제한한다

 

package com.giosis.util.qdrive.singapore.util

sealed class NetworkState 

sealed class는 같은 패키지에서만 상속 가능하다.

 

com.giosis.util.qdrive.singapore.setting안에 NetworkState를 상속 받는 클래스를 선언하려고 하면 다음과 같이 오류가 생성된다.

sealed class는 같은 패키지에 있는 자식 클래스에서만 상속 가능하다.

 

'kotlin 개인노트' 카테고리의 다른 글

(Kotlin) for문은 이제 그만  (0) 2022.06.24

+ Recent posts