관리 메뉴

나만을 위한 블로그

[이펙티브 코틀린] 아이템 44. 멤버 확장 함수의 사용을 피하라 본문

책/Effective Kotlin

[이펙티브 코틀린] 아이템 44. 멤버 확장 함수의 사용을 피하라

참깨빵위에참깨빵 2023. 4. 21. 22:36
728x90
반응형

어떤 클래스에 대한 확장 함수를 정의할 때 이를 멤버로 추가하는 건 옳지 않다. 확장 함수는 첫 번째 아규먼트로 리시버를 받는 단순한 일반 함수로 컴파일된다. 아래 함수는 그 아래 함수로 컴파일된다.

 

fun String.isPhoneNumber(): Boolean = length == 7 && all { it.isDigit() }
fun isPhoneNumber('$this': String): Boolean =
    '$this'.length == 7 && '$this'.all { it.isDigit() }

 

이렇게 단순하게 변환되기 때문에 확장 함수를 클래스 멤버로 정의할 수도 있고 인터페이스 안에 정의할 수도 있다.

 

interface PhoneBook {
    fun String.isPhoneNumber(): Boolean
}

class Fizz: PhoneBook {
    override fun String.isPhoneNumber(): Boolean =
        length == 7 && all { it.isDigit() }
}

 

이런 코드가 가능하지만 DSL을 만들 때를 제외하면 안 쓰는 게 좋다. 특히 가시성 제한을 위해 확장 함수를 멤버로 정의하는 건 굉장히 좋지 않다. 큰 이유는 가시성을 제한하지 못한다는 것이다. 이는 단순하게 확장 함수를 쓰는 형태를 어렵게 만들 뿐이다.

확장 함수의 가시성을 제한하고 싶다면 멤버로 만들지 말고 가시성 한정자를 붙인다. 멤버 확장을 피해야 하는 이유를 정리하면 아래와 같다.

 

  • 레퍼런스를 지원하지 않는다
  • 암묵적 접근을 할 때 두 리시버 중 어떤 리시버가 선택될지 혼동된다
  • 확장 함수가 외부의 다른 클래스를 리시버로 받을 때 해당 함수가 어떤 동작을 하는지 명확하지 않다
  • 경험 적은 개발자의 경우 확장 함수를 보면 직관적이지 않을 수 있다
반응형
Comments