안드로이드 개발자의 창고
[18일차 Kotlin] 고차 함수 본문
출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 PPT
📖 고차 함수
- 함수를 매개변수로 받거나 반환 타입이 함수인 함수를 고차 함수라고 부른다.
- 함수 호출 시 전달하는 함수와 반환 하는 함수는 람다식을 사용할 수도 있다.
📖 예제 코드
✔️ 매개변수로 함수를 받는 함수
fun testFunc1(a1:Int, a2:Int, m1:(Int, Int) -> Int){
val r1 = m1(a1, a2)
println("testFun1 r1 : $r1")
}
fun main(){
val t1 = fun(x1:Int, x2:Int) : Int{
return x1 + x2
}
testFunc1(100, 200, t1)
testFunc1(100, 200, fun(x1:Int, x2:Int) : Int {
return x1 - x2
})
val lambda1 = {x1:Int, x2:Int -> x1 * x2}
testFunc1(100, 200, lambda1)
testFunc1(100, 200, {x1:Int, x2:Int -> x1 / x2})
}
코드 해석
- testFunc1(100, 200, t1)
- t1은 함수를 호출할 때 전달할 익명 함수이다.
- 따라서 100, 200은 t1의 x1, x2에 전달되어 100 + 200 = 300이 출력된다.
- testFunc1(100, 200, fun(x1:Int, x2:Int) : Int { ... }
- 익명 함수를 따로 작성하지 않고 직접 작성해준 코드이다.
- 따라서 x1, x2에 100, 200이 전달되어 100 - 200 = -100이 출력된다.
- val lambda1 = {x1:Int, x2:Int -> x1 * x2}
- 고차함수에 람다 함수를 전달하는 것도 가능하다.
- 따라서 100, 200은 lambda1에 전달되어 100 * 200 = 20000이 출력된다.
- testFunc1(100, 200, {x1:Int, x2:Int -> x1 / x2})
- 람다식을 따로 작성하지 않고 직접 전달하는 것도 가능하다.
- 따라서 람다식에 100, 200이 전달되어 0이 출력된다.
✔️ 함수를 반환하는 함수
fun testFunc2(a1:Int) : (Int) -> Int{
return fun(x2:Int) : Int{
return a1 + x2
}
}
fun main(){
val t2 = testFunc2(100)
val r2 = t2(200)
println("r2 : $r2")
}
코드 해석
- 반환하는 함수 내부에서 지역변수나 매개변수를 사용할 수 있다.
- val t2 = testFunc2(100)
- 매개변수로 전달된 100은 매개변수 a1로 전달된다.
- val r2 = t2(200)
- t2에 전달된 200은 반환되는 함수의 매개변수 x2로 전달된다.
- 따라서 해당 고차 함수는 300이 출력된다.
✔️ 람다식을 반환하는 함수
fun testFunc3(a1:Int):(Int) -> Int{
return {x2:Int -> a1 - x2}
}
fun main(){
val t3 = testFun3(100)
val r3 = t3(200)
println("r3 : $r3")
}
코드 해석
- val t3 = testFun3(100)
- 매개변수로 전달된 100은 testFunc3의 a1으로 전달된다.
- val r3 = t3(200)
- 매개변수로 전달된 200은 람다식의 x2로 전달된다.
- 따라서 해당 함수는 -100이 출력된다.
✔️ 함수나 람다식을 받는 매개변수를 제일 마지막에 작성하지 않은 함수
fun testFunc4(a1:Int, m1:(Int, Int) -> Int, a2:Int){
val r4 = m1(a1, a2)
println("r4 : $r4")
}
fun main(){
// 1. 익명함수를 변수에 담아 전달한다.
val f4 = fun(x1:Int, x2:Int) : Int{
println("x1 : $x1")
println("x2 : $x2")
return x1 + x2
}
testFunc4(100, f4, 200)
// 2. 익명함수를 직접 작성한다.
testFunc4(100, fun(x1:Int, x2:Int) : Int{
println("x1 : $x1")
println("x2 : $x2")
return x1 + x2
}, 200)
// 3. 람다를 전달한다.
val lambda4 = {x1:Int, x2:Int ->
println("x1 : $x1")
println("x2 : $x2")
x1 + x2
}
testFunc4(100, lambda4, 200)
// 4. 람다를 직접 작성한다.
testFunc4(100, {x1:Int, x2:Int ->
println("x1 : $x1")
println("x2 : $x2")
x1 + x2
}, 200)
}
코드 해석
- testFunc4를 사용하는 main의 모든 코드는 익명함수의 x1에 100, x2에는 200이 전달된다.
- 따라서 x1 : 100, x2 : 200, r4 : 300이 출력된다.
✔️ 함수나 람다식을 받는 매개변수를 제일 마지막에 작성한 함수
fun testFunc5(a1:Int, a2:Int, m1:(Int, Int) -> Int){
val r5 = m1(a1, a2)
println("r5 : $r5")
}
fun main(){
testFunc5(100,200) { x1: Int, x2: Int ->
println("x1 : $x1")
println("x2 : $x2")
x1 + x2
}
}
코드 해석
- 위의 1 ~ 4 모두 사용 가능하다.
- { }로 직성한 람다식이 제일 마지막 매개변수로 들어간다.
- 해당 코드도 x1 : 100, x2 : 200, r4 : 300이 출력된다.
✔️ 메서드 오버라이딩과 고차함수의 비교
interface Inter1{
fun interMethod()
}
fun testFunc6(inter1:Inter1){
inter1.interMethod()
}
class InterClass1 : Inter1{
override fun interMethod() {
println("InterClass1의 interMethod")
}
}
class InterClass2 : Inter1{
override fun interMethod() {
println("InterClass2의 interMethod")
}
}
// --------------------------------------------------------
fun testFunc7(m1:() -> Unit){
m1()
}
fun main(){
val ic1 = InterClass1()
testFunc6(ic1)
val ic2 = InterClass2()
testFunc6(ic2)
testFunc6(object:Inter1{
override fun interMethod() {
println("익명 중첩 클래스의 메서드 호출")
}
})
// --------------------------------------------------------
testFunc7 {
println("testFun7 1번")
}
testFunc7 {
println("testFun7 2번")
}
}
코드 해석
- testFunc6()은 인터페이스와 메서드 오버라이딩을 통해 다른 곳에서 메서드 호출하는 함수이다.
- testFunc6()은 Java에서 제공하는 방식이다.
- testFunc7()은 고차함수를 통해 위의 작업을 대신하는 함수이다.
- main에서 testFunc7() 호출하며 람다식을 전달한다.
- testFunc7()은 Kotlin에서 고차함수를 지원하면서 작성할 수 있는 방식이다.
✔️ 고차함수의 it
fun testFunc8(m1:(Int) -> Unit){
m1(100)
}
fun main(){
testFunc8 { a1:Int ->
println(a1)
}
testFunc8 {
println(it)
}
}
코드 해석
- 매개변수 하나인 함수나 람다식을 받는 고차함수를 사용할 때, 전달할 함수나 람다식에 매개변수를 정의하지 않고 it을 사용하면 매개변수로 전달되는 값을 사용할 수 있다.
- 해당 코드에서는 it을 통해 100이 출력된다.
'Computer > Kotlin' 카테고리의 다른 글
[18일차 Kotlin] 연산자 오버로딩(Operator Overloading) (0) | 2023.05.23 |
---|---|
[18일차 Kotlin] Scope Function(범위 지정 함수 - let, apply, run, with, also) (0) | 2023.05.23 |
[17일차 Kotlin] Sealed Class (0) | 2023.05.20 |
[17일차 kotlin] 열거형 클래스(Enum Class) (0) | 2023.05.20 |
[17일차 Kotlin] Null 안전성을 위한 형변환(Null Casting) (0) | 2023.05.20 |