어떤 클래스에 대한 확장 함수를 정의할 때, 이를 멤버로 추가하는 것은 좋지 않다.
확장 함수는 첫 번째 아규먼트로 리시버를 받는 단순한 일반 함수로 컴파일된다.
그렇기 때문에, 확장 함수를 클래스 멤버로 정의할 수도 있고, 인터페이스 내부에 정의할수도 있다.
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
}
}
일반적으로는 탑 레벨(일반) 확장 함수를 사용하는 경우가 많다.