sealed
sealed Class는 sealed Class로 정의된 클래스의 종류에 따라 다른 작없을 처리해야 할 때 매우 유용하다.
enum클래스를 확장한 개념.
각 종류별로 하나의 인스턴스만 생성되어 있는 enum클래스와 달리 인스턴스를 여러개 생성 할 수 있다.
Java에서는 클래스에 final키워드를 붙이거나 생성자를 private로 생성하지 않는이상, 모든 클래스가 상속이 가능하기 때문에 악용의 우려가 있으므로 상속을 제한하는 클래스가 필요하다.
sealed 키워드를 클래스 앞에 붙이면 같은 프로젝트 안에서는 상속이 가능하고 외부 모듈에서는 상속이 불가해진다.
//sealed class를 상속받는 모든 하위 클래스들은 그 수퍼클래스에 중첩되어야 한다.
sealed class Expr {
data class Const(val number: Double): Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
}
//하지만 같은 파일내에 정의하는 경우, 클래스 외부에 선언해도 무방하다.
sealed class Expr {
object NotANumber : Expr()
}
data class Const(val number: Double): Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
fun eval(e: Expr): Double = when(e) {
is Const -> e.number
is Sum -> eval(e.e1) + eval(e.e2)
NotANumber -> Double.NaN -> // object타입은 별도 캐스팅을 할 필요가 없기때문에 is를 붙이지 않는다.
//가능한 모든 케이스들에 대해 분기를 작성해 주었기 때문에 else 문(기본분기)을 작성할 필요가 없다.
}
// enum class와 매우 유사하다. enum의 확장판.
// enum은 각 object들이 같은 생성자와 같은 함수들을 갖지만, sealed class는 object의 hierarchies 제한만 갖고
// 별도의 생성자와 프로퍼티를 가질 수 있다.
//sealed class를 상속받은 클래스는 꼭 같은 파일에 있을 필요는 없다.
만약 Expr 이 한정클래스가 아니라면 Expr 을 상속하는 클래스가 얼마든지 있을 수 있기에, when 문에 else 절이 반드시 필요하게 된다.
그리고 한정클래스에서는 새롭게 상속을 받는 클래스가 추가되게 되었을때 그 새로 추가된 유형의 처리가 없다면 컴파일에러를 뱉어주어서 새 유형에 대한 처리가 누락되는 것을 방지할 수 있지만, 비 한정클래스의 경우 컴파일단에서 에러가 잡히지 않기 때문에 런타임 에러가 발생할 수 있다.
enum class 와 매우 유사하다. enum 의 확장판. enum 은 각 object 들이 같은 생성자와 같은 함수들을 갖지만, sealed class는 object 의 hierarchies 제한만 갖고 별도의 생성자와 프로퍼티를 가질 수 있다.
sealed class를 상속받은 클래스는 꼭 같은 파일에 있을 필요는 없다.
인터페이스로도 같은효과를 낼 수 있다.
//Interface
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
fun eval(e: Expr): Int = when(e) {
is Num -> e.value
is Sum -> eval(e.right) + eval(e.left)
else -> throw IllegalArgumentException("Unknown expression")
//else분기를 처리해주어야만 한다.
}
비슷한 용법이지만 when표현식에서 else를 처리해 주어야만하는가 아닌가의 차이가 있다.
새로운 서브클래스를 추가해주어도 컴파일러가 그걸 알지못한다. 추가된 클래스에 따른 분기를 작성해주지 않으면 버그가 발생할 위험이 있다.
Sealed 나 enum 을 사용하게 되면 case 들이 명확해진다. 따라서 상정하지 않은 케이스를 사전에 방지하는 효과가 있고, 사전에 정의한 case 에 대해 실수로 인한 누락을 컴파일단에서 잡아준다. 즉 훨씬 안전하고 명확한 코딩을 할 수 있다.
Last updated