특정 클래스나 객체에서 호출 가능한 함수처럼 이름 없이 호출할 수 있게 도와주는 함수
class Greeter(val greeting: String) {
operator fun invoke(name: String) {
println("$greeting, $name!")
}
}
val greeter = Greeter("Hello")
// invoke 함수의 특별한 기능 : 이름 없이 호출이 가능하다.
// greeter.invoke("World")
greeter("World") // Hello, World!
특정한 이름의 함수를 사용하여 연산자의 동작을 재정의할 수 있게 해주는 기능으로, 연산자 오버로딩을 통해 사용자는 기존 연산자의 동작을 클래스나 타입에 맞게 재정의할 수 있다.
사전적 정의 : 이전부터 있었던 사례. 예로부터 전하여 내려오는 일 처리의 관습.
소프트웨어 관점 : 특별한 이름이 붙은 함수를 일반 메소드 호출 구문으로 호출하지 않고 더 간단한 다른 구문으로 호출할 수 있게 지원하는 기능
// 두 피연산자의 타입이 다른 연산자 정의하기
operator fun Point.times(scale: Double): Point {
return Point((x * scale).toInt(), (y * scale).toInt())
}
val p = Point(10, 20)
println(p * 1.5) // Point(x=15, y=30)
operator fun Double.times(point: Point): Point {
return Point((this * point.x).toInt(), (this * point.y).toInt())
}
fun main() {
val p = Point(10, 20)
println(1.5 * p) // Point(x=15, y=30)
}
+=
연산자에 그 함수를 사용한다.operator fun <T> MutableCollection<T>.plusAssign(element: T) {
this.add(element)
}
val numbers = ArrayList<Int>()
numbers += 42
println(numbers[0]) // 42
함수 타입인 변수는 인자 개수에 따라 적당한 FunctionN 인터페이스를 구현하는 클래스의 인스턴스를 저장하며, 그 클래스의 invoke 메소드 본문에는 람다의 본문이 들어간다.
// 코틀린
val processTheAnswer = { number: Int -> number.toString() }
fun processTheAnswer() {
val function: (Int) -> String = object : Function1<Int, String> {
override fun invoke(number: Int): String {
return number.toString()
}
}
}
// 자바로 컴파일된 코드
// Function인자의개수<인자1, 인자2, ..., 결과>
processTheAnswer {
new Function1<Integer, String>() {
@Override
public String invoke(Integer number) {
return number.toString();
}
}
}
fun foo(callback: (() -> Unit)?) {
if (callback != null) {
callback()
}
}
fun <T> Collection<T>.joinToString(
separator: String = ", ",
prefix: String = "",
postfix: String = "",
transform: ((T) -> String)? = null
): String {
val result = StringBuilder(prefix)
for ((index, element) in this.withIndex()) {
if (index > 0) result.append(separator)
val str = transform?.invoke(element)
?: element.toString()
result.append(str)
}
result.append(postfix)
return result.toString()
}