기본적으로 어떠한 Parent Class
를 상속받는 하위 클래스Chid Class
들이 여러개 존재할 경우 컴파일러는 Parent Class
의 하위 클래스들이 얼마나 존재하는지 알 수 없다.
따라서 when
을 통해 Parent Class
의 하위 클래스별로 다른 동작을 지정하고 싶을 경우 모든 자식 클래스에 대한 분기를 지정해도 컴파일러에서는 이를 알 수 없기때문에 반드시 else
가지를 생성해야만 에러가 없이 실행된다.
abstract class Attack
class SwordAttack: Attack()
class MagicAttack: Attack()
class BowAttack: Attack()
// 위와 같이 Attack클래스를 상속받았다고 할 경우
when (Attack()) {
is SwordAttack -> "근접공격 실행!"
is MagicAttack -> "마법공격 실행!"
is BowAttack -> "원거리공격 실행!"
else -> "공격 아님"
}
// 반드시 else 가지를 만들어야 컴파일 에러가 없다.
// 컴파일러가 Attack를 상속 받은 하위 클래스가 몇개인지 알 길이 없기 떄문이다.
sealed class
는 abstract class
를 상속받는 하위 클래스의 종류를 제한할 수 있는 특성을 가지고 있다.
그렇기 때문에 sealed class
를 사용할 경우 컴파일러에서 sealed class
의 하위 클래스 들을 특정할 수 있기때문에 else
가지를 사용하지 않아도 된다.
sealed class Attack
class SwordAttack: Attack()
class MagicAttack: Attack()
class BowAttack: Attack()
when (Attack()) {
is SwordAttack -> "근접공격 실행!"
is MagicAttack -> "마법공격 실행!"
is BowAttack -> "원거리공격 실행!"
}
// Attack를 sealed class로 선언할 경우 상속받은 세가지의 클래스만 있다고 특정할 수 있기때문에
// when을 사용할때 else가지를 사용하지 않아도 에러가 생기지 않는다.
sealed class
는 object
나 data class
와 함께 사용할 때 유용하며, 특히 recyclerView
의 View Type
를 사용할경우 효과적이다.
sealed class ContactItems(val ItemID: Long, open val location: String) {
data class Header(
...
override val location: String
) : ContactItems(headerID, location)
data class Contents(
...
override val location: String,
...
) : ContactItems(contentID, location)
}
위와 같이 하나의 데이터 리스트에 리사이클러뷰에 사용되는 다른 뷰타입의 정보를 담을 경우 유용하게 사용할 수 있다
sealed class
는 abstract class
를 상속받은 클래스이기때문에 sealed class
역시 직접적으로 인스턴스를 생성할 수 없다.
따라서 sealed class
의 프로퍼티나 메서드는 직접 참조할 수 없다.
그렇기 때문에 sealed class
의 하위 클래스들에 공통적으로 접근해야할 프로퍼티를 만들어야할 경우 open
프로퍼티로 선언한 뒤, 하위클래스에서 override
해서 사용해야 한다.
retrofit
사용을 위해 Gson
컨버터를 사용할 경우 프로퍼티를 override
해서 사용할 수 없기 때문에 여러개의 retrofit model
을 하나의 seald class
로 사용하고 싶은 경우에는 같은 프로퍼티 내용을 가지고 있더라도 다른 방법으로 접근해야 한다.일단 어떻게든 해가고 있는 거같은데..
잘 하고 있는거 맞나...?