Scope Function에는 5가지 함수들이 존재합니다!
Scope Function에 해당하는 함수들을 람다식을 이용하여 호출하면 일시적인 Scope(범위)가 생기고
이 범위 안에서는 전달된 객체에 대해 “it” 또는 “this”라는 Context Object를 통하여 접근할 수 있습니다.
이 함수들에는 두가지 차이점이 있습니다.
Scope Function 람다식 안에서 Context Object는 실제 객체명을 대신하여, this나 it을 통해 객체에 접근합니다.
class Person(var name: String, var age: Int)
fun main() {
val person = Person("노지환", 25)
person.run {
println("이름: ${this.name}") // this를 사용하여 진행할 수 있습니다.
println("나이: $age") // this를 생략해도 됩니다!
age = 26
}
println(person.age)
person.let {
println("이름: ${it.name}") //it은 생략할 수 없습니다!
println("나이: ${it.age}")
it.age = 25
}
}
run, with, apply는 Context Object를 “this”로 참조합니다!
class Person(var name: String, var age: Int)
fun main() {
val person = Person("노지환", 25)
person.run {
println("이름: ${this.name}")
println("나이: $age")
}
with(person) {
println("이름: ${this.name}")
println("나이: $age")
}
person.apply {
println("이름: ${this.name}")
println("나이: $age")
}
}
let, also는 Context Object를 “it”으로 참조합니다.
person.let { want -> // 이런식으로 전달 인자명을 설정할 수도 있습니다!
println("이름: ${want.name}")
want.name = "지환노"
}
person.also {
println("이름: ${it.name}")
}
apply, also의 반환값은 Context Object 객체 자체입니다.
따라서, 체인 형식으로 계속 호출이 가능합니다!
val numberList: MutableList<Double> = mutableListOf()
numberList.also { println("Populating the list") } // 이런식으로
.apply { // 연속적으로 사용하더라도, 반환값이 객체이기 때문에 사용이 가능하다!
add(2.71)
add(2.3)
add(4.5)
for (i in this) println(i)
}
.also { println("sorting") }
.sort() // 하지만 sort후에는
.run { // 반환값이 true, false이기 때문에 run을 사용할 때 this를 사용할 수 없다
for(i in numberList) println(i)
}
//.run 이 친구도 사용이 불가능하다! run의 return 값은 람다식 결과를 반환하기 때문에 객체를 가져올 수 없다.
게다가 Context Object를 반환하는 함수의 return 문에도 사용이 가능합니다!
fun getNumber(): Int {
return Random.nextInt(100).also {
println("return random number")
}
}
person.let {
println("-------------------------------")
println(it.name)
it.name = "지환노"
println(it.name)
it // -> 이런식으로 scope function이 종료될 때 객체를 넘길 수도 있다!!
}
println(person.name) // scope function 안에서 값을 변경하면 적용된다!
여러가지 Scope Function들의 권장 사용법을 알아봅시다!
val str: String? = "Hello"
val length = str?.let {
println("let() called on $it")
processNonNullString(it) // OK: 'it' is not null inside '?.let { }'
it.length
}
val numbers = mutableListOf("one", "two", "three")
with(numbers) {
println("'with' is called with argument $this")
println("It contains $size elements")
}
val service = MultiportService("https://example.kotlinlang.org", 80)
val result = service.run { // 요기에 null check도 가능하기 때문에 유용하다! service?.run
port = 8080
query(prepareRequest() + " to port $port")
}
val adam = Person("Adam").apply {
age = 32
city = "London"
}
println(adam)
val numbers = mutableListOf("one", "two", "three")
numbers
.also { println("The list elements before adding new one: $it") } // 이렇게 log 찍기 같이 하면 좋다!
.add("four")
Fuction | Context Object | Return Value |
---|---|---|
let | it | Lambda Result |
run | this | Lambda Result |
with | this | Lambda Result |
apply | this | Context Object |
also | it | Context Object |