[Kotlin] Sealed Class 란
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
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
}