PS 문제를 하나씩 풀다 보니, 공부가 필요하다고 느낀 문법에 대해 정리한 글입니다.
스코프 함수를 정리하다 보면 Context 객체와 관련된
this,it키워드가 등장합니다.
이번에는 컨텍스트 객체에 대해 정리해보려고 합니다.
공식 문서에 따르면, 컨텍스트 객체는
새롭게 형성된 람다 내부에서 현재 작업의 기준이 되는 객체라고 볼 수 있습니다.
범위 함수에 전달된 람다 내부에서는 컨텍스트 객체를 실제 이름 대신 짧은 참조로 사용할 수 있습니다.
각 스코프 함수는 컨텍스트 객체를 참조하는 두 가지 방식 중 하나를 사용합니다.
run,with,apply는 컨텍스트 객체를 lambda receiver로 참조하며, 이때this키워드를 사용합니다.
대부분의 경우 수신 객체의 멤버에 접근할 때this를 생략할 수 있기 때문에, 코드를 더 짧게 작성할 수 있습니다.
class ThisPerson(var name: String, var age: Int? = null)
fun main() {
val person = ThisPerson("smith", 28)
person.run {
println("이름 : ${this.name}")
println("나이 : ${this.age}")
}
val park = ThisPerson("Park").apply {
age = 28
}
park.run {
println("이름 : $name")
println("나이 : $age")
}
}
위 예제를 보면
ThisPerson이라는 클래스를 만들고,"smith"와28이라는 값을 넣어 객체를 생성하였습니다.
처음에는run스코프 함수를 통해 이름과 나이를 출력하고 있는데, 이때 객체를 다시 클래스 이름으로 접근하는 것이 아니라this를 통해 참조하고 있습니다.
즉, this는 현재 스코프에서 기준이 되는 객체 자신을 가리킬 때 사용됩니다.
대부분의 경우 수신 객체의 멤버에 접근할 때
this를 생략할 수 있으므로 코드가 더 짧아집니다.
반면this를 생략하면 수신 객체의 멤버와 외부 객체 또는 함수를 구분하기 어려워질 수도 있습니다.
따라서 컨텍스트 객체를 수신자(this)로 사용하는 방식은 다음과 같은 경우에 주로 권장됩니다.
it은let,also처럼 람다의 인자 이름을 따로 지정하지 않았을 때 사용되는 기본 이름입니다.
따라서this보다 짧게 사용할 수 있고, 표현식도 비교적 읽기 쉬워지는 경우가 많습니다.
다만 it은 객체를 인자로 받는 형태이기 때문에, this처럼 객체의 함수나 속성에 암묵적으로 접근할 수는 없습니다.
그래서 다음과 같은 경우에 자주 사용됩니다.
import kotlin.random.Random
fun writeToLog(message: String) {
println("INFO: $message")
}
fun main() {
fun getRandomInt(): Int {
return Random.nextInt(100).also {
writeToLog("getRandomInt()에 생성된 값 $it")
}
}
val i = getRandomInt()
println(i)
}
위 예제처럼 스코프 함수 안에서 인수 이름을 따로 지정하지 않으면,
람다 내부에서 암묵적으로it이라는 이름이 사용되는 것을 확인할 수 있습니다.
import kotlin.random.Random
fun writeToLog(message: String) {
println("INFO: $message")
}
fun main() {
fun getRandomInt(): Int {
return Random.nextInt(100).also { value ->
writeToLog("getRandomInt()에 생성된 값 $value")
}
}
val i = getRandomInt()
println(i)
}
또한 위와 같이 인수 이름을
value로 직접 지정하면,
it보다 의미가 더 분명해져서 코드의 의도를 더 쉽게 파악할 수 있습니다.
오늘은 Kotlin 스코프 함수에서 사용하는 Context Object에 대해 알아보았습니다.
this와it의 차이를 잘 이해하고 상황에 맞게 사용하면, 코드를 더 간결하고 읽기 쉽게 작성할 수 있습니다.