Programming Language/Kotlin

[Kotlin] Sealed Class 란

Tenacity_Dev 2023. 1. 1. 01:18
728x90

Sealed class란

Sealed class 및 interface는 상속에 대한 더 많은 제어를 제공하는 제한된 클래스 계층을 나타냅니다.

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

sealed interface Error

sealed class IOError(): Error

class FileReadError(val file: File): IOError()
class DatabaseError(val source: DataSource): IOError()

object RuntimeError : Error

어떤 의미에서 Sealed class 는 Enum class와 유사하다. Enum class에서 유형에 대한 값 집합도 제한되지만, 각 열거형 상수는 단일 인스턴스로만 존재하는 반면, Sealed class의 하위 클래스는 여러 인스턴스를 가질 수 있으며 각 인스턴스는 고유하다.

https://superohinsung.tistory.com/59

 

[Kotlin] Enum class란

Enum class 열거형 클래스는 형식이 안전한 열거형을 구현하는 것입니다. enum class Direction { NORTH, SOUTH, WEST, EAST } 내부의 각각의 상수들은 오브젝트이다. 각 열거형 상수는 개체이다. 열거형 상수는

superohinsung.tistory.com

Enum class에 대한 자세한 건 여기에 써 두었다.

 

Sealed class는 그 자체로 추상적이며 직접 인스턴스화 할 수 없으며, abstract 멤버를 가질 수 있다.

(추상 클래스로 직접 객체 인스턴스 생성이 불가하다.)

 

Sealed class의 생성자는 다음 두 가시성 중 하나를 가질 수 있습니다. (기본값은 protected 그리고 private)

sealed class IOError {
    constructor() { /*...*/ } // protected by default
    private constructor(description: String): this() { /*...*/ } // private is OK
    // public constructor(code: Int): this() {} // Error: public and internal are not allowed
}

 

Sealed class 및 interface의 직접 하위 클래스는 동일한 패키지에서 선언되어야 한다. 

최상위 수준이거나 다른 명명된 클래스, 명명된 인터페이스 또는 명명된 객체의 수에 관계없이 중첩될 수 있다.

하위 클래스는 Kotlin의 일반 상속 규착과 호환되는 한 모든 가시성을 가질 수 있다.

Sealed class의 하위 클래스에는 적절한 정규화된 이름이 있어야하며, 로컬 또는 익명 개체일 수 없다.

 

또한 enum 클래스는 sealed class를 확장 할 수 없지만 sealed interface를 구현 할 수 있다.

 

이러한 제한은 간접 하위 클래스에는 적용되지 않습니다. sealed class의 직접 하위 클래스가 sealed 된 것으로 표시되지 않는 경우 수정자가 허용하는 모든 방식으로 확장할 수 있습니다.

 

Sealed class 에서 when 표현

when은 Sealed class를 사용하는 주요 이점은 식에서 사용할때 나온다.

모든 경우를 포함하는지 확인할 수 있는 경우 문에 else절을 추가할 필요가 없다. 

그러나 이는 when이 명령문이 아닌 표현식으로 사용하는 경우에만 사용한다.

fun log(e: Error) = when(e) {
    is FileReadError -> { println("Error while reading file ${e.file}") }
    is DatabaseError -> { println("Error while reading from database ${e.source}") }
    is RuntimeError ->  { println("Runtime error") }
    // the `else` clause is not required because all the cases are covered
}

 

728x90