Archives
Recent Posts
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Today
Total
관리 메뉴

안드로이드 개발자의 창고

[18일차 Kotlin] 고차 함수 본문

Computer/Kotlin

[18일차 Kotlin] 고차 함수

Wise-99 2023. 5. 23. 01:35

 

 

출처 : 안드로이드 앱스쿨 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이 출력된다.