Skip to content

범위 지정 함수

범위 지정 함수는 특정 객체에 대한 작업을 블록 안에 넣어 실행할 수 있도록 하는 함수이다.

특정 객체에 대한 작업을 블록으로 묶으면 수행할 작업의 범위를 지정함으로써, 코드의 가독성을 개선할 수 있다.

코들린에서는 let, run, apply. also, with로 총 5가지의 기본 범위 지정함수를 지원한다.

하나씩 알아보도록 하자.

public inline fun <T> T.apply(block: T.() -> Unit): T
public inline fun <T, R> T.run(block: T.() -> R): R
public inline fun <T, R> with(receiver: T, block: T() -> R):R

apply

public inline fun <T> T.apply(block: T.() -> Unit): T

apply는 수신객체 내부 프로퍼티를 통해 작업한 다음 수신객체 자체를 반환하는 함수이다.

apply에서의 block은 람다식의 수신객체로 apply의 수신객체(T)를 지정하기 때문에 람다식 내부에서 수신객체에 대해 명시하지 않고 함수를 호출할 수 있다. (this 사용도 가능하다.)

apply를 사용하면

val user = User()
user.name = "rlaisqls"
user.age = 17

위와 같은 코드를

val user = User().apply {
name = "rlaisqls"
age = 17
}

이렇게 바꿀 수도 있다. user.과 같은 중복된 부분을 없앨 수 있다.

run

public inline fun <T, R> T.run(block: T.() -> R): R

run은 apply와 똑같이 동작하지만 수신 객체를 return하지 않고, run 블록의 마지막 라인을 return하는 범위 지정 함수이다.

val user = User("rlaisqls", 17)
val isUserAdult = user.run {
age = 20
isAdult()
}
println("isUserAdult : $isUserAdult") //true

run은 수신객체 없이도 동작할 수 있다. 다만 수신객체 없이 run을 사용하면 내부에 수신객체를 명시해줘야 한다.

with

public inline fun <T, R> with(receiver: T, block: T() -> R):R

with는 수신객체에 대한 작업 후 마지막 라인을 return한다. run과 완전히 똑같이 동작한다.

run은 확장 함수로 사용되지만 with은 수신객체를 파라미터로 받아 사용한다는 점이 차이점이다.

val user = User("rlaisqls", 17)
val isUserAdult = with(user) {
isAdult()
}
println("isUserAdult : $isUserAdult") //false

let

public inline fun <T, R> T.let(block: (T) -> R): R

let은 수신객체를 이용해 작업을 한 후 마지막 줄을 return 하는 함수이다.

수신객체를 접근할 때 it을 사용해야 한다는 것 빼고 run, with과 동작이 같다.

하지만 다른 범위 지정함수와 다르게 let은 null check를 한 후 실행하는 것이 가능하다.
(run과 with은 객체가 존재한다는 것을 가정하여 null이든 아니든 바로 동작한다.)

val user = null
val isUserAdult = user?.let {
isAdult()
}
println("isUserAdult : $isUserAdult") //null

null check가 되지 않았다면 NPE가 throw 됐겠지만, null check 이후 코드가 실행되어 에러가 뜨지 않고 실행된 것을 확인할 수 있다.

also

public inline fun <T> T.also(block: (T) -> Unit): T

also는 apply와 마찬가지로 수신객체 자신을 반환한다. apply가 프로퍼티를 세팅 후 객체 자체를 반환 하는데만 사용된다면, also는 프로퍼티 세팅 뿐만아니라 객체에 대한 추가적인 작업(로깅, 유효성 검사 등)을 한 후 객체를 반환할 때 사용된다.

also에서의 block은 람다식의 입력 파라미터로 also의 수신객체(T)를 지정하기 때문에 내부에서 수신객체를 사용하기 위해서는 it을 사용해야 한다.


공식문서 : https://kotlinlang.org/docs/scope-functions.html