본문 바로가기

코틀린

[Kotlin] Sealed Class (wordle 미션)

Sealed Class

sealed 클래스는 기본적으로 abstract 클래스이며 sealed 클래스를 상속받는 여러 서브 클래스들을 가질 수 있다.

sealed 클래스를 사용하면 보다 엄격하게 상속을 관리할 수 있다. 컴파일 시 컴파일러가 sealed 클래스를 상속받는 서브 클래스들을 모두 파악하고 있기 때문이다. 또한 컴파일 이후에는 서드파티 클라이언트가 sealed 클래스를 확장할 수 없다.

서브 클래스는 classdata classobject 모두 가능하다. 다만 상태 값이 바뀌지 않는 서브 클래스라면 object를 사용하는 것이 좋다.

인텔리제이에서 상태가 없는 클래스를 class 로 만들면 object 로 바꾸라는 경고가 뜬다.

Sealed Class의 특성

  • sealed 클래스의 서브 클래스들은 반드시 같은 파일 내에 선언되어야 한다.
  • sealed 클래스는 기본적으로 abstract 클래스이며 인스턴스화 될 수 없다.
  • sealed 클래스는 protected나 private 생성자만 갖는다.

적용

DSL 스터디 미션을 구현하면서 Sealed Class를 적용해보았다.

// Skill.kt
interface Skill

// HardSkill.kt
data class HardSkill(val value: String) : Skill

// SoftSkill.kt
data class SoftSkill(val value: String) : Skill

기존에는 interface를 사용하여 HardSkill과 SoftSkill를 각각의 data class 파일로 구현했다.

// Skill.kt
sealed class Skill

data class SoftSkill(val value: String) : Skill()
data class HardSkill(val value: String) : Skill()

리팩토링을 진행하며 Skill을 interface에서 sealed 클래스로 변경하였고, SoftSkill과 HardSkill을 같은 파일로 모았다.

여러 클래스를 한 파일에 넣는 것을 주저해서는 안 된다.
특히 각 클래스를 정의하는 소스코드 크기가 아주 작은 경우 더욱 그렇다.
(Kotlin In Action - p.77)

 

처음엔 여러 클래스를 한 파일에 넣는 것이 어색했는데 ‘Kotlin In Action’을 읽으면서 코틀린에서는 이게 어색한 일이 아니구나, 적절히 잘 사용해야겠다고 생각했다.


특히 when 절을 사용할 때 sealed 클래스의 특징을 잘 확인할 수 있다. sealed 클래스를 사용하지 않는 경우 컴파일러가 sealed 클래스의 서브 클래스들을 알지 못하기 때문에 반드시 else 절이 필요하다.

fun getSkillMessage(skill: Skill): String {
		return when (skill) {
				is SoftSkill -> "soft skill"
				is HardSkill -> "hard skill"
				else -> "no skill"
		}
}

이 경우 두 가지 문제점이 생길 수 있다.

  1. else 절이 없으면 컴파일 에러가 발생한다.
  2. 서브 클래스 중 하나를 빠트려도 컴파일 에러가 발생하지 않는다.

sealed 클래스를 사용하면 컴파일러가 sealed 클래스의 서브 클래스들을 알 수 있기 때문에 위 두 가지 문제점을 모두 해결할 수 있다.

fun getSkillMessage(skill: Skill): String {
		return when (skill) {
				is SoftSkill -> "soft skill"
				is HardSkill -> "hard skill"
		}
}

else 절이 없어도 컴파일 에러가 발생하지 않으며, 서브 클래스 중 하나라도 처리를 빠트리는 경우 컴파일 에러가 발생하여 문제를 바로 파악할 수 있다.

Enum과의 차이

enum도 값들을 제한한다는 점에서 비슷한 점이 있지만, enum의 경우 싱글톤으로 존재한다는 점에서 차이가 있다. 또한 enum 클래스와 달리 상속을 지원하기 때문에, 상속을 활용한 풍부한 동작을 구현할 수 있다.


references

Sealed classes | Kotlin

[Kotlin] Sealed Class 알아보기

[Kotlin] Kotlin sealed class란 무엇인가?