lambda with receiver (수신 객체 지정 람다)
개발을 하다 보면 객체를 반복 사용하면서 그 객체에 대한 연산을 명시하는 경우가 많습니다.
수신 객체 지정 람다는 이러한 수신 객체를 반복적으로 명시하지 않고도 람다의 본문 안에서 다른 객체의 메소드를 호출할 수 있게 합니다.
이런 람다를 수신 객체 지정 람다(lambda with receiver) 라고 합니다.
with 함수
/* with 없이 반복 사용하는 경우 */
val settings = webView.settings
settings.javaScriptEnabled = true
settings.javaScriptCanOpenWindowsAutomatically = true
settings.useWideViewPort = true
settings.loadWithOverviewMode = true
settings.builtInZoomControls = false
settings.domStorageEnabled = true
settings.defaultTextEncodingName = "UTF-8"
위 예제에서 WebView Setting을 위해 여러 메소드를 호출하면서 매번 settings를 반복 사용하는 것을 알 수가 있습니다.
이런 경우, 코드가 훨씬 더 길어지거나 반복을 자주해야한다면 어땠을까요?
그만큼 중복해서 쓰는 코드가 많아지는걸 보며 굉장히 개운치 않은 마음이 들게 될 겁니다...😨
이제 위의 예제를 with로 수정해보도록 하겠습니다.
/* with를 사용한 경우 */
val settings = webView.settings
with(settings) { //수신 객체 지정
javaScriptEnabled = true
javaScriptCanOpenWindowsAutomatically = true
useWideViewPort = true
loadWithOverviewMode = true
builtInZoomControls = false
domStorageEnabled = true
defaultTextEncodingName = "UTF-8"
}
기존에 반복해서 사용하던 settings가 제거되어 훨씬 간결하고 명확해서 가독성이 좋아진 것 같습니다! 😀
with문은 코틀린 언어가 제공하는 특별한 구문처럼 보이지만, 실제로는 파라미터가 2개인 함수입니다.
위의 예제를 기준으로 보면, with는 파라미터가 하나인것 처럼 보이지만 사실은 with(settings, { ... }) 형태로 첫 번째 파라미터는 settings 이고, 두 번째 파라미터는 람다입니다.
with가 반환하는 값은 람다 코드를 실행한 결과입니다.
람다는 괄호 밖으로 빼내어 작성하는 관례에 따라 with(settings) { ... } 로 쓰기 때문에 특별한 구문처럼 보이네요!
with 함수는 첫 번째 파라미터로 받은 객체를 두 번째 파라미터로 받은 람다의 수신 객체로 만들기 때문에 람다의 본문에서는 수신 객체의 멤버에 접근할 수 있습니다.
위 예제를 리팩토링해서 불필요한 val settings 를 없앨 수도 있습니다.
with(webView.settings) { //수신 객체 지정
javaScriptEnabled = true
javaScriptCanOpenWindowsAutomatically = true
useWideViewPort = true
loadWithOverviewMode = true
builtInZoomControls = false
domStorageEnabled = true
defaultTextEncodingName = "UTF-8"
}
apply 함수
apply 함수는 거의 with와 같습니다. 유일한 차이는 apply는 항상 자신에게 전달된 객체(수신 객체)를 반환한다는 점입니다.
fun createTitleTextView(context: Context, title: String): TextView {
return TextView(context).apply {
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
text = title
setTextColor(Color.BLACK)
setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15f)
}
}
위 예제에서 apply는 아래와 같이 사용됩니다.
1. 새로운 TextView를 만들고
2. 즉시 그 객체가 apply에 전달되어 람다 안에서는 TextView가 수신 객체가 됩니다.
3. 따라서 원하는 대로 TextView의 메소드를 호출하거나 프로퍼티를 설정할 수 있고
4. 최종적으로 apply 람다에 의해 초기화된 TextView 객체가 반환됩니다.
apply는 전달받은 객체를 다시 반환하기 때문에 객체를 생성하면서 즉시 객체의 프로퍼티를 초기화해야 하는 경우 굉장히 유용합니다.
'코틀린' 카테고리의 다른 글
코틀린(Kotlin) - 타입 시스템 as?, !!, let, lateinit (0) | 2021.03.24 |
---|---|
코틀린(Kotlin) - 타입 시스템 null 가능성 safe call(?.) elvis(?:) (0) | 2021.03.21 |
안드로이드 코루틴 기본 개념과 활용까지의 모든 것! (3) | 2021.03.08 |
코틀린(Kotlin) - 함수형 인터페이스 활용 (0) | 2021.02.24 |
코틀린(Kotlin) - 지연 계산(lazy) 컬렉션 연산 : Sequence (0) | 2020.04.24 |