※ 람다를 사용하는 방법에 대해서는 자세히 다루지 않습니다.
람다를 받는 함수를 정의하는 방법
fun main(args: Array<String>) {
doSomething{ a, b ->
println("a + b = ${a + b}")
}
// 파라미터를 사용하지 않는 경우
doSomething{ _, b ->
println("b = ${b}")
}
}
fun doSomething(action: (a: Int, b: Int)->(Unit)) {
action(2, 3)
}
람다 파라미터의 타입은 (파라미터: 타입)->(반환 타입) 형식이다. 위 코드와 같이 정의하고 사용할 수 있다. 만약 사용하지 않는 파라미터가 있다면 _ 기호를 사용해 명시할 수 있다.
인스턴스를 함수처럼 사용하는 방법
fun main(args: Array<String>) {
val add = Add()
add.invoke(2, 3)
add(2, 3)
}
class Add {
operator fun invoke(a: Int, b: Int) {
println("a + b = ${a + b}")
}
}
클래스 내부에 invoke 메소드를 구현하면 인스턴스 이름과 () 의 조합으로 invoke 함수를 호출할 수 있다. 인스턴스.invoke() 로 호출하는 것과 동일하다. invoke 메소드 앞에는 operator 키워드를 붙여주어야 한다.
Java 에서 람다는 어떻게 컴파일 될까?
fun main(args: Array<String>) {
doSomething(
object : Function2<Int, Int, Unit> {
override fun invoke(p1: Int, p2: Int) {
println("p1 + p2 = ${p1 + p2}")
}
}
)
}
fun doSomething(action: (a: Int, b: Int)->(Unit)) {
action(2, 3)
}
// FunctionN 인터페이스
// P1, P2, P3, ... , N : 파라미터 타입
// R : 반환 타입
// Function1
interface Function1<in P1, out R> {
operator fun invoke(p1: P1) : R
}
람다는 Java 에서 위와 같은 코드로 해석되어 컴파일 된다. 따라서 Java 와 Kotlin 사이에 호환이 가능하다. FunctionN 인터페이스는 N + 1 개의 타입 파라미터를 받는다. N 개는 invoke 메소드의 파라미터의 타입이고 나머지 한 개는 invoke 메소드의 반환 타입이다. in 과 out 키워드에 대해서 궁금하다면 제네릭, 공변성, 반공변성에 대해서 찾아보면 된다.
그런데 어째서인지 FunctionN 과 비슷한 인터페이스를 직접 정의해서 넘겨주었을 때는 컴파일이 안 된다...
'java & kotlin' 카테고리의 다른 글
[RxKotlin] 2. Observable (콜드 옵저버블, 핫 옵저버블, Subject) (0) | 2022.02.20 |
---|---|
[RxKotlin] 1. 기본 개념 (Observable 과 Observer) (0) | 2022.02.11 |
[kotlin] 고차함수와 람다 (0) | 2021.12.13 |
[kotlin] 구조 분해 선언 (0) | 2021.12.11 |
thread safe vs thread unsafe (1) | 2021.03.30 |