-
코틀린 수신 객체 지정 람다 : with와 applyKotlin 2020. 8. 7. 15:48
이 글은 'Kotlin in Action' 을 보고 공부한 내용을 정리하고자 작성한 글입니다.
더 자세한 내용은 해당 책을 참고하시기 바랍니다.개요
코틀린을 사용하다보면 처음 접하는 생소한 메소드나 예약어가 있습니다. 오늘 소개하려는 with와 apply도 그 중 하나죠. 안드로이드 프레임워크에서도 많이 사용되는 메소드다보니 이 메소드들을 볼 수 있는 기회는 많았으나 따로 찾아봐도 어떻게 사용해야하는지 잘 와닿지 않았습니다. 또, 이 두 메소드를 잘 사용하면 진짜 코틀린답게 코드를 짜는 것처럼 보인다고 해야하나..뭔가 코드 작성을 잘 하는 것처럼 보이기도 했습니다. 어쨌든 이번에 Kotlin in Action을 공부하면서 좋은 내용이 있어 정리하고자 합니다. 여기서 말하는 수신 객체 지정 람다가 개인적으로는 가장 이해하기 쉬웠습니다.
수신 객체 지정 람다란?
코드를 작성하다보면 수신 객체, 즉 사용하는 객체를 반복해서 명시하는 경우가 많습니다. 수신 객체 지정 람다는 이런 수신 객체를 명시하지 않고 람다의 본문 안에서 다른 객체의 메소드를 호출할 수 있게 하는 것입니다. 이런 람다를 수신 객체 지정 람다라고 부릅니다.
With 함수
with를 더 잘 이해하기 위해 예를 한번 들어보겠습니다.
fun alphabet(): String { val result = StringBuilder() for (letter in 'A'..'Z') { result.append(letter) } result.append("\nNow I know this alphabet!") return result.toString() }
알파벳을 문자열에 담아서 반환해주는 함수입니다. 이 함수를 보면 result가 자주 반복되는 것을 알 수 있죠. 이 함수에서는 현재 4번이 반복됐지만 만약 코드가 더 길어지거나 더 반복을 자주해야한다면 어떻게 될까요? 그만큼 중복해서 작성하는 코드가 많아질 수 밖에 없겠죠.
이런 문제를 해결하기 위해 with를 사용할 수 있습니다. with를 사용해서 위의 코드를 수정해보겠습니다.
fun alphabet(): String { val stringBuilder = StringBuilder() return with(stringBuilder) { for (letter in 'A'..'Z') { this.append(letter) } append("\nNow I know this alphabet!") this.toString() } }
위와 같이 result에 대한 중복을 제거했습니다. with 함수는 첫 번째 인자로 받은 객체를 두 번째 인자로 받은 람다의 수신 객체로 만듭니다. 위에서는 인자가 하나인 것처럼 보이지만 사실 with는 with(stringBuilder, { ... }) 와 같은 람다 함수인거죠. 람다 본문에서는 this를 사용해 그 수신 객체에 접근할 수 있고, 또 this 없이도 수신 객체의 프로퍼티나 메소드에 접근 가능합니다.
여기서 불필요한 stringBuilder 변수를 제거할 수도 있습니다.
fun alphabet(): String = with(StringBuilder()) { for (letter in 'A'..'Z') { append(letter) } append("\nNow I know this alphabet!") toString() } }
이렇게 불필요한 stringBuilder 변수를 없애면 alphabet 함수가 식의 결과를 바로 반환하게 됩니다. 따라서 식을 본문으로 하는 함수를 표현할 수 있는 것이죠. 이 함수는 람다 식의 본문에 있는 마지막 식의 값을 반환하게 됩니다. 만약 람다의 결과 대신 식을 적용한 수신 객체 자체가 필요하면 어떻게 해야할까요? 이럴 때, apply 함수를 사용합니다.
Apply 함수
apply 함수는 거의 with와 같습니다. 유일한 차이란 apply는 항상 자신에게 전달된 객체를 반환한다는 점입니다.
fun alphabet(): String = StringBuilder().apply { for (letter in 'A'..'Z') { append(letter) } append("\nNow I know this alphabet!") }.toString()
이런 식으로 리팩토링 할 수 있는데요. apply 함수는 특히 객체의 인스턴스를 만들면서 즉시 프로퍼티 중 일부를 초기화해야되는 경우에 유용합니다.
'Kotlin' 카테고리의 다른 글
Kotlin의 고차 함수 (0) 2021.05.23 Kotlin의 Null 처리 (0) 2021.05.17 [코틀린을 다루는 기술] Kotlin에서의 재귀 함수 사용 (0) 2020.08.07 [코틀린을 다루는 기술] 코틀린 함수 정리 (0) 2020.07.31 [Kotlin] 배열 사용법 정리 (2) 2020.02.20