Scope Function은 객체를 기반으로 코드 블록을 실행하는 데 사용된다.
Kotlin에는 let, run, with, apply, also 총 5개가 있다.
run, with, apply는 객체 참조로 this를 사용한다.
this는 객체의 멤버에 접근할 때 생략할 수 있어 코드가 더 짧아진다. 하지만 외부 객체와 구분하기 어려울 수 있다.
따라서 주로 함수를 호출하거나 속성에 값을 할당하여 객체의 멤버에서 작동하는 lambda에서 권장된다.
val adam = Person("Adam").apply {
age = 20 // same as this.age = 20
city = "London"
}
println(adam)
let, also는 객체 참조로 it을 사용한다.
객체를 함수 호출의 인자로 사용할 경우 또는 여러 변수를 같이 사용해야하는 경우 유용하다.
val number = 42
number.let {
println(it) // 단순히 객체 출력
processNumber(it) // 객체를 함수의 인자로 전달
}
apply, also는 객체를 반환한다.
따라서 객체의 초기화나 설정 작업에 유용하다.
val person = Person("Alice").apply {
age = 30 // 객체의 속성을 변경
city = "New York" // 객체의 속성을 변경
}
함수의 반환 값으로도 사용 가능하다.
fun getRandomInt(): Int {
return Random.nextInt(100).also {
writeToLog("getRandomInt() generated value $it")
}
}
let, run, with는 람다 결과를 반환한다.
따라서 결과를 변수에 할당하거나 결과에 대한 연산을 할 때 유용하다.
val numbers = mutableListOf("one", "two", "three")
val countEndsWithE = numbers.run {
add("four")
add("five")
count { it.endsWith("e") }
}
반환값 없이 로컬 변수에 대한 임시 scope를 생성할 수도 있다.
val numbers = mutableListOf("one", "two", "three")
with(numbers) {
val firstItem = first()
val lastItem = last()
println("First item: $firstItem, last item: $lastItem")
}
연쇄된 결과에 대한 결과를 작업할 수 있다.
val numbers = mutableListOf("one", "two", "three", "four", "five")
numbers.map { it.length }.filter { it > 3 }.let(::println)
?.을 통해 non-null 값인 scope를 실행하는데 사용할 수 있다.
val str: String? = "Hello"
//processNonNullString(str) // compilation error: str can be null
val length = str?.let {
println("let() called on $it")
processNonNullString(it) // OK: 'it' is not null inside '?.let { }'
it.length
}
"with this object, do the following"
반환된 결과를 사용할 필요가 없을 때 사용하는 것이 좋다.
val numbers = mutableListOf("one", "two", "three")
with(numbers) {
println("'with' is called with argument $this")
println("It contains $size elements")
}
" run the code block and compute the result. "
객체를 생성과 동시에 반환 값을 계산할 때 유용하다.
val service = MultiportService("https://example.kotlinlang.org", 80)
val result = service.run {
port = 8080
query(prepareRequest() + " to port $port")
}
일반 함수로도 사용할 수 있다.
val hexNumberRegex = run {
val digits = "0-9"
val hexDigits = "A-Fa-f"
val sign = "+-"
Regex("[$sign]?[$digits$hexDigits]+")
}
"apply the following assignments to the object. "
객체를 생성할 때 주로 사용한다.
val adam = Person("Adam").apply {
age = 32
city = "London"
}
" and also do the following with the object. "
객체 자체를 참조할 때 사용한다.
val numbers = mutableListOf("one", "two", "three")
numbers
.also { println("The list elements before adding new one: $it") }
.add("four")
| 함수 이름 | 객체 참조 방식 | 확장 함수 | 반환 값 | 사용 예시 |
|---|---|---|---|---|
| let | it | 람다 결과 | O | 객체가 null이 아니면 실행, 체이닝된 결과 처리 |
| with | this | 람다 결과 | X | 반환 값이 필요 없을 때, 객체를 소개할 때 |
| run | this | 람다 결과 | Both | 객체 구성과 결과 계산을 동시에 할 때 |
| apply | this | 객체 자체 | O | 객체 초기화 및 설정을 할 때 |
| also | it | 객체 자체 | O | 부수적인 작업을 수행할 때 |