[Effective Kotlin] 아이템 39. 태그 클래스 보다는 클래스 계층을 사용하라

0

상수 모드를 가진 클래스를 꽤 많이 볼수 있다.

이러한 상수 모드를 "tag"라고 부르며, 태그를 포함한 클래스를 태그 클래스라고 부른다.

하지만 서로 다른 책임을 한 클래스에 태그로 구분해서 넣는다는것에 문제가 시작된다.

class ValueMatcher<T> private constructor(
    private val value: T? = null,
    private val matcher: Matcher
){
    fun match(value : T?) = when(matcher){
        Matcher.EQAUL -> value == this.value
        Matcher.NOT_EQUAL -> value != this.value
        Matcher.LIST_EMPTY -> value is List<*> && value.isEmpty()
    }

    enum class Matcher {
        EQAUL,
        NOT_EQUAL,
        LIST_EMPTY
    }
    
    
    fun <T> equal(value: T) =ValueMatcher<T>(value, Matcher.EQAUL)
    fun <T> notEqual(value: T) =ValueMatcher<T>(value, Matcher.NOT_EQUAL)
    
}
  • 한 클래스에 여러 모드를 처리하기 위한 상용구가 추가된다.

  • 여러목적을 위해 쓰여야 하므로,프로퍼티가 일관적이지않게 사용될 수 있고, 더많은 프로퍼티가 필요하다.

  • 여러목적을 가지고, 여러 방법으로 설정할 수 있는 경에는 상태의 일관성과 정확성을 지키기 어렵다.

그래서 한 클래스에 여러 모드를 만드는 대신, 각각의 모드를 여러 클래스로 만들기 시작했다.

sealed class SealedValueMatcher<T>{
    abstract fun match(value: T): Boolean

    class Eqaul<T>(val value: T) : SealedValueMatcher<T>(){
        override fun match(value: T): Boolean  = value ==this.value
    }

    class NotEqaul<T>(val value: T) : SealedValueMatcher<T>(){
        override fun match(value: T): Boolean  = value !=this.value
    }
}

sealed 한정자

sealed 한정자는 외부에서 추가적인 서브클래스를 만들수 없음을 보장하므로, else브랜치를 만들 필요가 없다.

반면 abstract class는 개발자가 새로운 인스턴스를 만들수 있다.

profile
쉽게 가르칠수 있도록 노력하자

0개의 댓글