클래스와 오브젝트#2 - 봉인된 클래스

2019, Jun 16    

Sealed(봉인된)클래스는 클래스 상속을 제한하고자 할때 사용된다.
앞에서 공부한 바와 같이 When식(expression)은 반드시 ‘else’를 포함해야 한다.
그런데 when의 인자가 반드시 특정값에 해당 한다고 가정 했을때(enum처럼) 굳이 default인 case를 두어 처리해야 한다는 불편함이 생긴다.

interface Expr

class Num(val value:Int) : Expr

class Sum(val left: Expr, val right: Expr) : Expr

//when절에 else 분기가 반드시 존재해야 함.
fun eval(e:Expr) : Int =
        when (e) {
            is Num -> e.value
            is Sum -> eval(e.right) + eval(e.left)
            else ->
                throw IllegalArgumentException("Unknown expression")
        }

Sealed(봉인된)클래스는 이와 같은 상황을 해결할 수 있게 해준다. sealed 클래스를 선언하기 위해서는 class명 앞에 sealed변경자(modifier)
을 넣으면 된다. 봉인된 클래스는 하위 클래스를 가질수 있지만 같은 파일 내에서 봉인된 클래스 내에 중첩 클래스로 선언해야만 한다.

//sealed 키워드를 통한 봉인된 클래스 선언
sealed class SealedExpr {
  //봉인된 클래스를 상속 받는 중첩 클래스들
    class Num(val value:Int) : SealedExpr()
    class Sum(val left: SealedExpr, val right: SealedExpr) : SealedExpr()
}

fun _eval(e: SealedExpr) : Int =
        when(e) {
            is SealedExpr.Num -> e.value
            is SealedExpr.Sum -> _eval(e.right) + _eval(e.left)
            //'else'분기가 없지만 오류가 발생하지 않는다.
        }

위와 같이 when식에 else분기가 없이 처리 가능한 이유는 봉인된 클래스 SealedExpr은 내부(중첩)클래스인 Num, Sum이외에 다른 값을 가질 수 없기 때문이다.
sealedClass
[봉인된 클래스는 클래스 외부에 자신을 상속한 클래스를 둘 수 없다.] ]