예를들어
abstract class MenuItem
class EntreeItem : MenuItem
class SideDishItem : MenuItem
class AccompanimentItem : MenuItem
위와같이 하나의 추상클래스를 3개의 클래스가 상속했다고 가정해봅시다.
fun getItem(menuState : MenuItem){
return when(menuState){
is Entree -> "Entree"
is SideDish -> "SideDish"
is Accompaniment -> "Accompaniment"
}
위와 같이 Item의 상태를 확인하는 함수를 사용하면 else branch를 만들라는 오류가 나옵니다.
이러한 오류가 발생하는 이유는 컴파일러가 MenuItem를 상속받는 하위 클래스를 모르기 때문에 3개말고도 다른 클래스가 나올 수 있다고 판단하였기 때문입니다.
옳바른 문법
fun getItem(menuState : MenuItem){
return when(menuState){
is Entree -> "Entree"
is SideDish -> "SideDish"
is Accompaniment -> "Accompaniment"
else -> "No Item"
}
is Accompaniment 제거
fun getItem(menuState : MenuItem){
return when(menuState){
is Entree -> "Entree"
is SideDish -> "SideDish"
else -> "No Item"
}
하지만 위와 같이 is Accompaniment를 제거해도 에러는 발생하지 않습니다. 이 역시 컴파일러가 MenuItem를 상속받는 하위 클래스를 모르기 때문에 발생하며 이런 경우 디버깅 난이도가 올라갑니다.
부모 클래스 하나에 여러 자식클래스가 상속되어 있다고 생각해봅시다. 컴파일러에선 각각의 자식 클래스가 부모클래스를 상속했다고만 인지하지 몇개의 어떤 자식클래스가 부모 클래스를 상속했는지는 알지 못합니다. 이러한 문제를 해결하기 위한 것이 sealed class 입니다.
예를들어
sealed class MenuItem
class EntreeItem : MenuItem
class SideDishItem : MenuItem
class AccompanimentItem : MenuItem
처음에 선언했던 MenuItem을 sealed class로 선언하였습니다.
fun getItem(menuState : MenuItem){
return when(menuState){
is Entree -> "Entree"
is SideDish -> "SideDish"
is Accompaniment -> "Accompaniment"
}
그럼 위에선 에러가 났던 메소드가 정상적으로 실행되는 것을 알 수 있습니다.
이유는 sealed class를 사용했기 때문에 컴파일러가 EntreeItem, SideDishItem,AccompaniimentItem 3가지만 자식클래스임을 알기 때문입니다.
is Accompaniment 제거
fun getItem(menuState : MenuItem){
return when(menuState){
is Entree -> "Entree"
is SideDish -> "SideDish"
}
따라서 is Accompaniment를 제거하면 에러가 나오는 것을 알 수 있습니다.
sealed class로 상속받는 클래스는 변수가 있거나 equals를 override 할 경우에만 class를 사용하고 그외에 경우엔 object를 사용해 싱글톤으로 입력받는게 메모리 효율에 좋다.