오늘부터 Jetpack Compose, RxJava를 공부하기로 했다. 그런데 내가 코틀린 겉핥기만 하고 있었는지 let, apply, run, with와 같은 키워드 / 메소드를 안 쓴다. 그래서 오늘 정리하면서 공부하기로 했다.
let
fun <T, R> T.let(block: (T) -> R): R
함수를 호출하는 객체를 이어지는 블록의 인자로 넘기고, 블록의 결과값을 반환. 한 번만 사용되고 더 이상 사용되지 않는 상수 값을 let을 이용하면 불필요한 선언을 방지할 수 있음.
Before
val v = MyClass.getValue(CONSTANT_VALUE)
myFuction(v.value1, v.value2, v.value3, v.value4)
After
MyClass.getValue(CONSTANT_VALUE).let { v ->
myFunction(v.value1, v.value2, v.value3, v.value4)
}
그리고 람다식의 인자가 하나라면 it으로 하면 된다고 한다. 그리고 null-safe 체크할 때도 할 수 있는데, 지정된 값이 null이 아닌 경우 코드를 실행해야 할 때 ~~~?.let {} 이렇게 하면 된다고 한다. 굳이 값 선언하고 if (~~ != null) 할 필요 X.
apply
fun <T> T.apply(block: T.() -> Unit): T
함수를 호출하는 객체를 이어지는 블록의 리시버로 전달하고 객체를 반환하는 함수.
리시버 : 바로 이어지는 블록 내에서 메소드 및 속성에 바로 접근할 수 있도록 하는 객체.
속성을 '적용'한다고 외우면 편할 것 같다.
Before
val item = Item()
item.value1 = "abc"
item.value2 = 20
item.value3 = false
After
val item = Item().apply {
value1 = "abc"
value2 = 20
value3 = false
}
run
fun <R> run(block: () -> R): R
fun <T, R> T.run(block: T.() -> R): R
인자가 없는 익명 함수처럼 동작하는 형태와 객체에서 호출하는 형태 이렇게 두 가지의 형태가 있다고 한다.
특정 객체의 메소드나 필드를 연속적으로 호출하거나 값을 할당할 때 사용하므로 apply랑 비슷한데, apply는 새 객체 생성함과 동시에 연속된 작업이 필요할 때, run은 이미 생성된 객체에 연속된 작업이 필요할 때 사용한다.
with
fun <T, R> with(receiver: T, block: T.() -> R): R
인자로 받는 객체를 이어지는 블록의 리시버로 전달하며 블록의 결과값을 반환한다.
run 함수랑 사실상 동일한데 리시버로 전달할 객체가 어디에 위치하는지만 다르다고 한다. run 함수 = let + with.
override fun onCreate(savedInstanceState: Bundle?) {
...
supportActionBar?.run {
setDisplayHomeAsUpEnabled(true)
setHomeAsUpIndicator(R.drawable.ic_clear_white)
}
...
supportActionBar?.let {
with(it) {
setDisplayHomeAsUpEnabled(true)
setHomeAsUpIndicator(R.drawable.ic_clear_white)
}
...
}
이 두 개가 같은 역할이라고 한다.
참고 블로그 및 문서
https://www.androidhuman.com/lecture/kotlin/2016/07/06/kotlin_let_apply_run_with/
코틀린의 유용한 함수들 - let, apply, run, with
#Android, #Koltin, and #Tesla
www.androidhuman.com
코틀린 의 apply, with, let, also, run 은 언제 사용하는가?
원문 : “Kotlin Scoping Functions apply vs. with, let, also, and run”
medium.com