1. 함수 참조
함수 타입의 변수는 이미 선언되어 있는 함수나 객체의 멤버 함수를 가리킬 수도 있다.
함수 이름 앞에 :: 를 붙이면, 표현식의 값은 그 함수의 참조값이 되며, 타입은 그 함수의 시그니처에 맞는 함수 타입이 된다.(코틀린 1.1 버전까지는 ::plus가 아닌 this::plus 형태로 적어야 한다)
객체의 멤버 함수를 함수 타입의 표현식으로 바꾸려면 '참조 변수::멤버 함수'의 꼴로 적는다.
fun plus(a: Int, b: Int) = println("plus 호출됨 ${a + b}")
object Object {
fun minus(a: Int, b: Int) = println("Object의 minus 호출됨 ${a - b}")
}
class Class {
fun average(a: Int, b: Int) = println("Class average 호출됨 ${(a + b) / 2}")
}
fun main() {
var instantFunc: (Int, Int) -> Unit
instantFunc = ::plus
instantFunc(60, 50) // plus 호출됨 110
instantFunc = Object::minus
instantFunc(36, 12) // Object의 minus 호출됨 24
instantFunc = Class()::average
instantFunc(25, 5) // Class average 호출됨 15
}
2. 고차 함수
고차함수란? 인수로 함수를 받거나, 함수를 반환하는 함수를 뜻한다.
함수 리터럴은 보통 고차 함수를 위해 사용된다.
고차 함수는 다음과 같이 반복적으로 같은 내용을 출력하는 상황에서 사용하면 유용하다.(함수를 호출하기 전/후에 수행해야 할 고정적인 작업이 있을 때)
아래와 같이 어떤 작업을 시작하고 끝날 때 마다 작업 시작, 작업 끝을 출력하려고 한다면..
println("=== 작업 시작 ===")
val a = 10
val b = 5
println("$a + $b = ${a + b}")
println("=== 작업 끝 ===")
println("=== 작업 시작 ===")
println("some")
println("task")
println("=== 작업 끝 ===")
고차 함수를 통해서 아래와 같이 만들 수 있다.
fun decorate(task:() -> Unit) {
println("=== 작업 시작 ===")
task() // task 매개변수가 가리키는 함수를 호출하고 있다.
println("=== 작업 끝 ===")
}
fun main() {
// decorate 함수에 함수 리터럴을 인수로 전달하고 있다.
decorate({
val a = 10; val b = 5
println("$a + $b = ${a + b}")
})
decorate({
println("some"); println("task")
})
}
만약, 고차 함수의 마지막 매개변수 타입이 함수 타입이라면, 함수 호출시 소괄호를 생략할 수 있다.
decorator({...})을 decorator{...}
고차 함수의 매개변수가 여러 개이고, 함수 타입의 매개변수가 맨 마지막에 온다면, 일반 인수들만 소괄호로 감싸고 함수 리터럴은 바깥으로 뺄 수 있다.
decorator(인수1, 인수2, ...) {...}
3. 클로저(Closure)
지역 변수는 항상 자신이 소속된 블록이 끝나면 소멸하는데 클로저(Closure)를 이용하여 지역 변수가 소멸하지 않는 것처럼 보이도록 할 수 있다.
// () -> Unit 타입의 함수를 반환하는 returnFunc 함수 선언
fun returnFunc(num: Int): () -> Unit = { println(num) }
fun main() {
// returnFunc 함수가 반환한 함수를 f 잠조 변수에 저장
val f: () -> Unit = returnFunc(30)
f()
}
위의 예제 코드를 살펴보자
f를 호출하면 num 매개변수가 사라지고 없을텐데 위의 main 안에 있는 코드가 가능한 이유는 함수 리터럴이 자신이 만들어질 때의 상황을 기억하고 있기 때문이다.
함수 리터럴이 만들어지는 순간 함수 리터럴은 자기 주변의 상황을 함께 저장한다.
즉, 함수가 만들어질 때 num 매개변수의 값을 복사해 갖고 있는다.
이렇게 함수가 만들어질 때 주변 상황을 기억하는 함수를 클로저라고 한다.
'TIL > Kotlin' 카테고리의 다른 글
[TIL/Kotlin] 코틀린 고급문법_클래스와 인터페이스에서 제네릭 사용하기, 제네릭이 적용된 인터페이스/클래스 상속·구현하기, 특정 타입을 상속·구현하는 타입만 인수로 받기 (0) | 2023.05.26 |
---|---|
[TIL/Kotlin] 코틀린 고급문법_리시버가 붙은 함수리터럴, 제네릭(Generic), 여러 타입을 인수로 받기, 구체화된 타입 매개변수 (0) | 2023.05.26 |
[TIL/Kotlin] 코틀린 고급문법_함수 리터럴과 람다식, 익명 함수, it 식별자 (0) | 2023.05.24 |
[TIL/Kotlin] 코틀린 고급문법_데이터 클래스와 객체 분해하기 (0) | 2023.05.21 |
[TIL/Kotlin] 코틀린 고급문법_중첩 클래스와 내부 클래스 (0) | 2023.05.21 |