코틀린 (Kotlin) 내부 클래스 sealed class 정리

내부 클래스

자바에서 내부 클래스는 바깥쪽 클래스에 대해 참조를 합니다.
그래서 static class 로 선언하여 바깥쪽 클래스에 대한 참조를 제거할 수 있습니다.

코틀린에서는 기본적으로 static 중첩 클래스와 같습니다.
그리고 바깥쪽 클래스에 대한 참조를 갖고 싶으면 inner 변경자를 붙입니다.

class Button : View {

    override fun getCurrentState(): State {
        return ButtonState()
    }

    //내부 클래스
    class ButtonState: State {
        fun save() {
            getCurrentState() //error! 바깥쪽 참조를 할 수 없다
        }
    }

   //inner class 로 바깥쪽 클래스 참조 가능
   inner class ButtonStateInner:State {

        fun save() {
            getCurrentState() //바깥쪽 클래스 참조 가능
        }

        fun getOuterReference() {
            //this@클래스 로 접근 또는 생략가능
            this@Button.getCurrentState() //바깥쪽 클래스 참조 가능
        }
    }
}

sealed class

코틀린에서는 상위 클래스를 상속한 하위 클래스 정의를 제한할 수 있습니다.

sealed class Expr { //sealed class 는 open 
    class Num(val value:Int) : Expr()
    class Sum(val left: Expr, val right: Expr) : Expr()
    class Total() //when 에 추가를 하지않은 경우 컴파일 에러
}


fun eval(e: Expr) : Int =
        //Expr 에 중첩 클래스 추가시 컴파일 에러 발생
        when(e) {
            is Expr.Num -> e.value
            is Expr.Sum -> eval(e.right) + eval(e.left)
            //else -> //else 가 필요 없다
        }

eval() 함수에서 when 구문은 항상 else 로 조건 처리를 해야됩니다.
하지만 상위클래스에 sealed class 를 붙이고 하위 클래스를 정의하면 when 식이 하위 클래스를 검사하기 때문에 else 구문이 필요없습니다.

그리고 Expr 클래스 안에 새로운 하위 클래스를 추가한경우 eval() 함수의 when 에서 새로 추가한 클래스 조건 검사를 추가하지 않은 경우 컴파일 에러가 발생합니다.

이는 클래스를 비교해서 처리해야되는 로직에서 유지보수시 신규 클래스를 추가하고 조건 검사 로직에서 누락되어 예외사항이 발생시키는 상황을 방지할 수 있습니다.
  • sealed class 는 자동으로 open 변경자가 붙습니다.
  • sealed class 는 private 생성자이기때문에 객체를 직접 생성 할 수 없습니다.
  • sealed class 는 같은 파일내에서 상속받아 하위 클래스를 구현할 수 있습니다.
  • sealed class 는 data class 에서 상속받아 하위 클래스를 구현할 수 있습니다.

//같은 파일 data 클래스에서 상속 가능
data class ExprData(val name: String) : Expr() {

}

//같은 파일 클래스에서 상속 가능
class ExprFile : Expr() {

}



댓글

이 블로그의 인기 게시물

코틀린 (Kotlin) filter, map, all, any, count, find, groupBy, flatMap 함수 정리

코틀린 (Kotlin) 인터페이스 정리

RecyclerView 에서 notifyItemChanged()의 payload 이해하기