Sealed Class와 Enum Class 정리
오늘은 Kotlin의 Sealed Class와 Enum Class에 대해 알아보겠습니다.
- SealedClass
- Sealed 와 When
- Enum
- Enum Iterate
1. Sealed Class
1-1. Sealed Class
Seal의 뜻은 밀봉하다, 봉인하다는 뜻 인데요.
SealedClass는 abstract클래스여서,
객체로 만들수 없는 자신과,
자신을 직접 상속받는 서브클래스나 interface 들로 구성되어 있습니다.
외부의 다른 Class들은 이 sealed클래스로부터 상속을 받을 수 없도록 봉인되어 있습니다.
이렇게 외부에서 확장되지 않은 밀봉된 구조를 가짐으로서, 컴파일타임에 코드를 작성하면서, 서브클래스들에 접근해서 사용이 가능해 지는 것 이지요.
이 서브클래스들은 각각의 특성에 따라서 다양한 생성자를 가질 수 있는데요.
데이터를 받아서 상태가 변하지 않고 한번만 객체가 생성되는 타입일경우 object키워드를 붙여서 사용하면 되구요.
data클래스도 상속받아서 사용도 가능합니다.
class는 당연히 되구 말이지요.
아래와 같이 다양한 서브클래스들을 만들어서 사용할 수 있습니다.
enum에서 했던 것처럼 아래와 같이도 표현할 수 있습니다.
Sealed Class에서는 state(상태 값)을 포함하고 있는 여러개의 instance를 가질 수 있구요.
위에서 보았던 것처럼, 생성자도 각각의 특징에 따라서 다르게 가져갈 수 있습니다.
정적인 상태가 아니라, 다양한 state를 가질 수도 있구요.
Sealed Class가 훨씬 융통성이 있는 Class라고 할 수 있겠습니다.
1-2. Sealed Interface
Sealed Interface는 Sealed Class의 생성자를 가지고 있지 않은 Interface 버전을 말합니다.
생성자를 필요로 하지 않을 때 사용하면 되겠지요.
2. Sealed 와 When
Sealed Class는 When과 함께 사용되어질 때 강력해 집니다.
예를들어, networkState에 따라서 when문을 사용하여 경우의 수를 코딩해 주어야 할 때 편리한데요.
아래에서, when문을 작성할 때 안드로이드스튜디오의 도움을 받아서,
alt + Enter로 나오는 메뉴에서 Add remaining branches를 선택해주면 자동으로 모든 경우의 수들을 완성해 줍니다.
이제 else없는 when문을 채워서 사용해 주기만 하면 되네요.
3. Enum
Sealed Class는 진화된 Enum클래스라고 하시는 분도 있구요.
공식문서에도 어떤 면에서,
Enum 클래스의 확장이라고도 설명하고 있습니다.
Sealed Class가 새로운 클래스이면서,
Enum클래스보다 유연하고 다양한 형태를 지원하기 때문인데요.
그래서인지, Enum은 이제 사용할 필요가 없는 것처럼 생각되기도 하는데요.
정말 그런 것 일까요?
Enum에서 생성자의 형태가 모두 동일해야 하다는 것이 단점일 경우도 있지만,
그렇지 않을 때도 많습니다.
생성자를 동일하게 가져가는 경우도 상당히 많습니다.
아직은 Enum을 버릴 때가 아닙니다.
4. Enum Iterate
4-1. values()
게다가 enum만 가진 장점 중 하나는 다음과 같이 iterate이 가능하다는 장점도 있는데요.
융통성없는 enum이기에 가능한 것이기도 합니다.
아래와 같이 values()함수나, enumValues함수를 사용해 주면 됩니다.
아래와 같이 enumValueOf() 또는 valueOf() 함수를 사용해 enum값을 가져올수도 있습니다.
When을 이용해 else없이 Sealed Class와 쓰는 방법들을 Enum에서도 똑같이 적용할 수 있구요.
이러한 장점들을 보았을 때, 굳이 enum을 deprecated 된 것처럼 버릴필요는 없을 것 같네요.
만약, enum으로 작성했다가 sealed class를 써야하겠다는 생각이 들면, 그 때 IDE의 도움을 얻어서 쉽게 전환할 수 있습니다.
enum키워드 아래에서 우측마우스 버튼을 누르고 나오는 메뉴에서 아래의 Convert to sealed class 를 선택해 주면 됩니다.
4-2. entries
Kotlin1.9부터는 enum class안에서 entries에 직접 접근해,
enum 항목의 모든 리스트를 제공받을 수 있는데요.
아래와 같이 쉽게 사용할 수 있습니다.
enum class Color {
RED, GREEN, BLUE
}
fun main() {
// entries를 사용하여 모든 enum 상수에 접근
for (color in Color.entries) {
println(color.name)
}
// entries를 리스트로 사용
val colorList = Color.entries.toList()
println("Colors: $colorList")
// entries를 사용한 필터링
val primaryColors = Color.entries.filter { it == Color.RED || it == Color.BLUE }
println("Primary colors: $primaryColors")
}
5. 정리
Sealed Class건 Enum Class이건,
장점과 단점들이 있으므로 필요한 경우에 맞춰 잘 사용하면 될 것 같습니다.