Scope Functions
범위 지정 함수
- 수신 객체, 수신 객체 지정 람다 두가지 구성 요소를 가지는 함수.
수신 객체와 수신 객체 지정 람다는 어떤걸 의미할까?
ex)
Human("Kim", 30, "Seoul").let {
println(it)
it.moveTo("Busan")
it.incrementAge()
println(it)
}
위의 코드에서 Human 객체를 리시버, let 다음의 { } 부분을 람다함수라고 한다.
해당 람다 함수에서 Human 객체에 접근할 수 있다.
해당 함수들을 이용하면 객체에 접근하는 방법을 쉽게 해주고 코드가 간결해지고 가독성이 높아지는 장점이 있다.
1. with()
inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
with() 함수 : 인자로 객체를 받고 블록에서 수행된 결과를 반환하는 함수
- Non-nullable 수신 객체 이고 결과가 필요하지 않은 경우에만 with 를 사용
ex)
val person: Person = getPerson()
with(person) {
print(name)
print(age)
}
2. also()
inline fun <T> T.also(block: (T) -> Unit): T {
block(this)
return this
}
also() 함수 : apply 함수와 마찬가지로 객체를 반환하며 let 과 동작이 매우 유사한 함수 하지만 let 에서는 내부 결과를 변화 시킬 수 있지만 also 에서는 변화 시킬 수 없다.
- 수신 객체 람다가 전달된 수신 객체를 전혀 사용 하지 않거나 수신 객체의 속성을 변경하지 않고 사용하는 경우 also 를 사용한다.
- also 는 apply 와 마찬가지로 수신 객체를 반환 하므로 블록 함수가 다른 값을 반환 해야하는 경우에는 also 를 사용할수 없다.
- 예를 들자면, 객체의 사이드 이팩트를 확인하거나 수신 객체의 프로퍼티에 데이터를 할당하기 전에 해당 데이터의 유효성을 검사 할 때 매우 유용
ex)
class Book(author: Person) {
val author = author.also {
requireNotNull(it.age)
print(it.name)
}
}
val numbers = mutableListOf("one", "two", "three")
numbers
.also { println("The list elements before adding new one: $it") }
.add("four")
3. apply()
inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
apply() 함수 : 블록에 자기 자신을 전달하고 이 객체를 반환하는 함수
- 수신 객체 람다 내부에서 수신 객체의 함수를 사용하지 않고 수신 객체 자신을 다시 반환 하려는 경우에 apply 를 사용하며 대표적인 경우가 객체의 초기화
ex)
val human = Human().apply {
name = "Kim"
age = 30
}
4. let()
inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
let() 함수 : 블록에 자기 자신을 전달하고 수행된 결과를 반환하는 함수
- 지정된 값이 null 이 아닌 경우에 코드를 실행해야 하는 경우.
- Nullable 객체를 다른 Nullable 객체로 변환하는 경우.
- 단일 지역 변수의 범위를 제한 하는 경우.
ex)
var str="1"
val result=str?.let{// Int
Integer.parseInt(it)
}
println(result)
5. run()
inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}
run() 함수 : 익명함수처럼 사용하거나, 블록에 자기 자신을 전달하고 수행된 결과를 반환하는 함수
- 어떤 값을 계산할 필요가 있거나 여러개의 지역 변수의 범위를 제한하려면 run 을 사용한다.
- 매개 변수로 전달된 명시적 수신객체 를 암시적 수신 객체로 변환 할때 run ()을 사용할수 있다.
ex)
val avg =run{
val korean =100
val english= 80
val math=50
(korean+english+math)/3.0
}
println(avg)
· 범위 지정 함수 의 호출시에 수신 객체가 매개 변수로 명시적으로 전달되거나 수신 객체의 확장 함수로 암시적 수신 객체 로 전달된다.
· 범위 지정 함수 의 수신 객체 지정 람다 에 전달되는 수신 객체가 명시적 매개 변수 로 전달 되거나 수신 객체의 확장 함수로 암시적 수신 객체로 코드 블록 내부로 전달 된다.
· 범위 지정 함수의 결과로 수신 객체를 그대로 반환하거나 수신 객체 지정 람다 의 실행 결과를 반환한다.
· 객체에 접근하는 방법은 this와 it(람다 인자)가 있다.
· run, with, apply는 this를 사용하여 객체에 접근하고 let과 also는 it를 사용한다.
· apply, also 는 리시버객체를 리턴한다.
· let, run, with 는 람다 함수의 마지막 결과를 리턴한다.
https://medium.com/@fatihcoskun/kotlin-scoping-functions-apply-vs-with-let-also-run-816e4efb75f5
참고자료
'Android 개인공부' 카테고리의 다른 글
Android Custom Progress Dialog (0) | 2021.06.12 |
---|---|
AAC LifeCycles (0) | 2020.12.16 |
Kotlin? (0) | 2020.11.26 |
FCM 푸쉬메시지 테스트 앱 (0) | 2020.08.27 |
Gradle 동일 모듈 충돌시 해결 (0) | 2020.08.20 |