Sealed Class의 배경
컴파일러는 여러 개의 자식 Class들이 하나의 부모 Class를 상속받을 때 부모 Class와 자식 Class들의 연관성을 알지 못한다.
예를 들어 자동차의 행위에 대해 String을 리턴하는 코드를 작성한다고 생각해보자.
행위에 대한 3가지로 가는 상태(Drive), 멈추는 상태(Stop), 대기 상태(Stay)가 있다고 해보자.
abstract class Vehicle
object Go: Vehicle()
object Stop: Vehicle()
object Stay: Vehicle()
그리고 각 행위에 알맞은 String값을 리턴한다고 가정했을 때 아래와 같은 코드를 만들게 된다.
fun getAction(action: Vehicle): String {
return when (action) {
is Drive -> "Vehicle driving"
is Stop -> "Vehicle stopped"
is Wait -> "Vehicle waiting"
}
}
하지만 위의 코드는 'when' expression must be exhaustive, add necessary 'else' branch 에러를 낸다.
왜냐하면 컴파일러는 위에서 말했듯이 Vehicle을 상속받는 자식 Class들이 뭐가 있는지 모르기 때문이다.
그러므로 단순히 else 브랜치를 추가하여 오류를 해결할 수 있다.
fun getAction(action: Vehicle): String {
return when (action) {
is Drive -> "Vehicle driving"
is Stop -> "Vehicle stopped"
else -> "No action"
}
}
물론 Wait 행위에 대한 별도의 처리가 불필요하여 의도적으로 else로 통합하여 처리한 것일 수도 있지만,
만약 의도되지 않았다면 Wait에 대한 처리가 없는 것은 명백한 오류가 된다.
이러한 처리를 명백하게 하기 위해 Sealed Class를 사용한다.
Sealed Class는 추상 클래스로 상속받는 자식 클래스들을 명세하는 특성을 가지고 있다.
다시 말해 컴파일러가 Sealed Class를 상속받은 자식 클래스들을 알고 있다.
위에서 작성한 코드를 Sealed Class로 변경해보자.
Sealed Class 특징
sealed class Vehicle
object Drive : Vehicle()
object Stop : Vehicle()
object Wait : Vehicle()
이렇게만 바꿔줘도 아래와 같은 getAction 메소드에서 에러는 발생하지 않는다.
fun getAction(action: Vehicle): String {
return when (action) {
is Drive -> "Vehicle driving"
is Stop -> "Vehicle stopped"
is Wait -> "Vehicle waiting"
}
}
여기서 자동차의 행위 Drift를 추가한다고 가정해보자
sealed class Vehicle
object Drive : Vehicle()
object Stop : Vehicle()
object Wait : Vehicle()
object Drift : Vehicle()
fun getAction(action: Vehicle): String {
return when (action) {
is Drive -> "Vehicle driving"
is Stop -> "Vehicle stopped"
is Wait -> "Vehicle waiting"
}
}
Drift에 대한 처리가 없으므로 'when' expression must be exhaustive, add necessary 'is Drift' branch or 'else' branch instead 에러를 낸다.
그러므로 Drift에 대한 처리를 해주거나 else 브랜치를 추가하여 에러를 해결할 수 있다.
위에서 살펴본 바로는 컴파일러가 Sealed Class를 상속받는 자식 클래스들을 모두 알고 있다고 했다.
그럼 혹시?
엄청 큰 프로젝트라고 가정하면 컴파일러는 모든 패키지를 돌아다니며 자식 클래스들을 찾고 있을까?
물론 아니다.
Sealed Classs는 자식 클래스에 대한 선언을 동일한 패키지 내로 제한하기 때문에 불필요한 리소스를 소모하지 않는다. 그러므로 서로 다른 패키지에 존재하는 Class가 Sealed Class를 상속받을 수 없고, Sealed Class는 Abstract이기 때문에 별도로 인스턴스를 생성할 수 없다.
'Kotlin' 카테고리의 다른 글
[Kotlin] Flow (0) | 2021.08.13 |
---|---|
[Kotlin] 리스트를 통한 명령형 방식과 함수형 방식 비교 (0) | 2021.08.04 |
[Kotlin] 커링(Currying) 함수 (0) | 2021.08.03 |
[Kotlin] Tailrec (0) | 2021.08.02 |
[코틀린] apply, with, let, also, run의 용도 (0) | 2021.03.17 |