어떤 클래스에 대한 확장 함수를 정의할 때, 이를 멤버로 추가하는 것은 좋지 않다.

확장 함수는 첫 번째 아규먼트로 리시버를 받는 단순한 일반 함수로 컴파일된다.

그렇기 때문에, 확장 함수를 클래스 멤버로 정의할 수도 있고, 인터페이스 내부에 정의할수도 있다.

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

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

위와 같이 사용할 수 있지만, DSL을 만들 때를 제외하면 이를 사용하지 않는 것이 좋습니다. 특히나 목표가 가시성의 제한 이라면 특히 좋지 않다. 아래와 같은 코드는 좋지 못한 코드이다.

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

왜냐하면 위와 같은 코드는 가시성을 제한하지 못하고, 단순히 확장 함수의 사용을 어렵게 할 뿐이다.

위 함수는 아래와 같이 사용해야 한다.

fun test(){
    // 불가능
    "1234567890".isPhoneNumber()
    // 가능
    PhoneBookIncorrect().apply { "1234567890".isPhoneNumber() }
}

그렇기 때문에 확장 함수의 가시성을 제한하고 싶다면, 멤버로 만들지 말고, 가시성 한정자를 붙여 주면 된다.

추가적인 이유로는

    val ref = String::isPhoneNumber
    val str = "1234567890"
    val boundedRef =str::isPhoneNumber

    val refX = PhoneBookIncorrect::isPhoneNumber // 오륲
    val book = PhoneBookIncorrect()
    val boundedRefX = book::isPhoneNumber // 오류
class A {
    val a = 10
}

class B {
    val a = 20
    val b = 30
    fun A.test() = a + b

    fun test() {
        val a = A()
        println(a.test())
        //40
    }
}

일반적으로는 탑 레벨(일반) 확장 함수를 사용하는 경우가 많다.