코틀린 문법 - Sealed classes and interfaces

kimgwon·2025년 1월 1일

Kotlin

목록 보기
19/19

🫧 Sealed

Sealed는 봉인된이라는 뜻으로, 상속 가능한 자식 클래스를 제한하는데 사용한다.
모든 자식 클래스는 컴파일 타임에 미리 정의된다. 예측 가능한 계층 구조로 안정적인 코드를 작성할 수 있다.



🫧 사용 예시

✏️ 1. 상속을 제한하고 싶을 때

자식 클래스가 미리 정해져야 하는 경우이다.

예시로 살펴보자.
abstract로 선언한 경우 컴파일러에서 인식하지 못하기 때문에, 선언한 클래스가 BlueCat, RedCat, GreenCat 세 개임에도 불구하고 else문을 따로 작성해줘야 한다.

val cat: Cat = BlueCat()
val result = when(cat) {
	is BlueCat -> "blue"
    is RedCat -> "red"
    is GreenCat -> "green"
    else -> "none"
}

abstract class Cat
class BlueCat: Cat()
class RedCat: Cat()
class GreenCat: Cat()

하지만 sealed로 선언한 경우 컴파일러가 자식 클래스를 인식하기 때문에, else를 작성하지 않아도 된다.

val cat: Cat = BlueCat()
val result = when(cat) {
	is BlueCat -> "blue"
    is RedCat -> "red"
    is GreenCat -> "green"
}

seaeld class Cat
class BlueCat: Cat()
class RedCat: Cat()
class GreenCat: Cat()

✏️ 2. 안전한 타입 설계가 필요할 때

상태 관리, 조건 분기 등에서 안전한 처리를 보장한다.

앱에서 데이터를 로드하는 동안, 여러 상태를 처리해야 한다.

// UI 상태를 정의하는 Sealed 클래스
sealed class UIState {
    object Loading : UIState() // 로딩 중
    data class Success(val data: String) : UIState() // 성공, 데이터 포함
    data class Error(val exception: Throwable) : UIState() // 실패, 예외 포함
}

// UI 상태에 따라 화면을 업데이트하는 함수
fun updateUI(state: UIState) {
    when (state) {
        is UIState.Loading -> println("로딩 중...") // 로딩 중 UI 표시
        is UIState.Success -> println("성공: ${state.data}") // 데이터를 화면에 표시
        is UIState.Error -> println("에러 발생: ${state.exception.message}") // 에러 메시지 표시
    }
}

✏️ 3. API를 안전하게 관리하고 싶을 때

외부에서 임의로 확장할 수 없도록 설계할 수 있다.

open class로 선언하여 확장이 가능한 경우, 예외가 발생할 수 있다.

// 일반적인 클래스를 사용
open class ApiResponse

// 클라이언트가 새로운 상태를 추가
class CustomResponse : ApiResponse()

sealed class를 사용하여 상속 가능한 자식 클래스를 제한할 수 있다.

// API 응답을 나타내는 sealed class
sealed class ApiResponse {
    data class Success(val data: String) : ApiResponse()
    data class Error(val message: String) : ApiResponse()
    object Loading : ApiResponse()
}

// 라이브러리에서 응답을 처리하는 함수
fun handleResponse(response: ApiResponse) {
    when (response) {
        is ApiResponse.Success -> println("성공: ${response.data}")
        is ApiResponse.Error -> println("에러: ${response.message}")
        ApiResponse.Loading -> println("로딩 중...")
        // else가 필요하지 않음: sealed class는 모든 상태가 컴파일 타임에 정의되므로
    }
}

sealed class로 선언했을 경우, 클라이언트에서 새로운 상태를 정의하려고 하면 컴파일 에러가 발생한다.

// 컴파일 에러 발생: ApiResponse는 sealed class이므로 외부에서 상속 불가
class CustomResponse : ApiResponse()


🫧 활용 예시

// 에러 처리 클래스
sealed class ErrorType {
    data class NetworkError(val code: Int) : ErrorType()
    data class ServerError(val message: String) : ErrorType()
    object UnknownError : ErrorType()
}

// 인증 상태 관리
sealed class AuthState {
    object LoggedIn : AuthState()
    object LoggedOut : AuthState()
    data class Error(val reason: String) : AuthState()
}

0개의 댓글