[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개의 댓글

관련 채용 정보