본문 바로가기
2023년 이전/kotlin

kotlin - 수신 객체 지정 람다

by JeongUPark 2020. 3. 10.
반응형

[출처 -  Kotlin In Action] [아래 내용들은 Kotlin In Action을 공부하면서 스스로 정리한 내용입니다] 

자바의 람다에는 없는 코틀린 람다의 독특한 기능이 있습니다. 그 기능은 수신 객체를 명시하지 않고 람다의 본문 안에서 다른 객체의 메소드를 호출할 수 있게 하는 것인데, 이를 수신 객체 지정 람다라고 부릅니다. 

여기서는 수신객체지정 람다를 활용하는 with와 apply에 대해 알아 보겠습니다. 이 두개는 여기서 간단한 설명을 확인 할 수 있습니다.

with

다음 코드를 보면

fun alphabet(): String {
    val result = StringBuilder()
    for (letter in 'A'..'Z') {
         result.append(letter)
    }
    result.append("\nNow I know the alphabet!")
    return result.toString()
}

fun main(args: Array<String>) {
    println(alphabet())
}

변수 result가 반복적으로 사용되고 있습니다. (이 정도는 사용할만 하지만, code가 더 많이 사용하는 경우도 많이 있을 것입니다.) 이 예제를 wtih를 사용하여 변경하면

fun alphabet(): String {
    val stringBuilder = StringBuilder()
    return with(stringBuilder) {
        for (letter in 'A'..'Z') {
            this.append(letter)
        }
        append("\nNow I know the alphabet!")
        this.toString()
    }
}

fun main(args: Array<String>) {
    println(alphabet())
}

 

with 함수는 인자로 받은 객체를 괄호{ }안에 람다 수신객체로 만듭니다. 인자로 받은 람다 본문에서 this를 사용하여 그 수신 객체에 접근할 수도 있습니다. 즉 위 코드에서 stringBuilder는 this로도 대체 됩니다.(this없이 수신객체를 사용할 수 도 있습니다. 위에서는 append("\nNow I know the alphabet!") 처럼)

또한, 위의 alphabet을 더 수정하여 변수 stringBuilder를 없앨 수 도 있습니다.

fun alphabet() = with(StringBuilder()) {
    for (letter in 'A'..'Z') {
        append(letter)
    }
    append("\nNow I know the alphabet!")
    toString()
}

with가 반환하는 값은 람다 코드를 실행한 결과 값이며, 이 값은 람다식의 마지막 식입니다.

 

그리고 alphabet이 OuterClass에 포함된 메소드인데 with에서 OuterClass에 정의된 .toString을 부르고 싶다면 다음과 같이

this@OuterClass.toString

this에 레이블을 붙이면 호출 하고 싶은 메소드를 명확하게 정할 수 있습니다.

apply

apply 함수는 with와 거의 같습니다. 차이점은 apply는 수신객체를 반환하고, 확장함수로 사용된다는 점입니다. (with는 확장함수가 아닙니다.) 

fun alphabet() = StringBuilder().apply {
    for (letter in 'A'..'Z') {
        append(letter)
    }
    append("\nNow I know the alphabet!")
}.toString()

위 code를 보면 apply는 확장함수로 정의되는 것을 할 수 있습니다. 그리고 그 확장함수를 호출한 인자가 수신객체가 되며, 이 수신객체가 람다의 수신객체가 됩니다.

이런 apply는 객체의 인스턴스를 만들면서 즉시 프로퍼티 중 일부를 초기화해야 한느 경우 유용하게 사용 됩니다. 자바에서는 보통 Builder 객체가 이 역할을 담당합니다. 

예를 들어 android에 TextView를 만들때 다음과 같이

TextView(context).apply{
	text = "Sample Text"
    textSize = 20.0
}

이렇게 새로운 TextView 인스턴스를 만들고 그 즉시 그 인스턴스를 apply에 넘겨 apply의 람다에서 TextView의 프로퍼티를 바로 설정할 수 있습니다. 이렇게 람다가 실행된 결과를 통하여 apply는 람다에 의해 초기화된 TextView의 인스턴스를 반환하게 됩니다.

반응형