Scope Function
When you call such a function on an object with a lambda expression provided, it forms a temporary scope.
In this scope, you can access the object without its name.
코틀린에서는 객체 내부에서 코드를 실행할 수 있는 여러 함수가 제공된다. 그들 중 일부는 람다 표현식이 제공되고, 그에 따라 임시 스코프가 형성된다. 이 스코프에서는 객체의 이름을 사용하지 않고 it, this를 활용해 객체에 접근이 가능한데, 이러한 함수를 scope function 이라고 한다.
개인적으로 사용은 할 줄 알지만, 언제 어떻게 사용하는지에 대한 적절한 판단까지 가능한가 ? 라는 물음에는 그렇다고 답하기 어려운것 같아 이번 기회에 정리해서 포스팅하기로 했다.
코틀린 스코프 함수는 다음과 같다.
- let
- fun
- with
- apply
- also
위 함수들은 모두 코드블록을 실행하고, 각 함수마다 블록 안에서 무엇이 되어서 나오는지에 차이를 가지므로 의도에 맞게 사용하면된다.
function | object reference | return value | Is extension function |
let | it | Lambda result | Yes |
run | this | Lambda result | Yes |
run | - | Lambda result | No: called without the context object |
with | this | Lambda result | No: takes the context object as an argument. |
apply | this | Context object | Yes |
also | it | Context object | Yes |
코틀린 공식문서에서 가이드로 제공하는 사용 추천 상황은 다음과 같다.
- non-null 객체에 람다를 실행하는 경우 -> let
- 로컬 범위에서 표현식을 변수로 도입하기 -> let
- 객체 구성하기 -> apply
- 객체 구성 및 결과 계산하기 -> run
- 표현식이 필요한 곳에서 실행하기 -> 확장함수가 아닌 run
- 추가적인 효과 주기 -> with
let
val numbers = mutableListOf("one", "two", "three", "four", "five")
val resultList = numbers.map { it.length }.filter { it > 3 }
// [5,4,4]
- 호출 체인의 결과에 대해 하나 이상의 함수를 호출한다
- null이 아닌 값을 포함하는 코드 블록을 실행하는 데 사용된다 ?.let{ } 구문
- 참조 키워드 : it / 이름 직접 부여
- 리턴 타입 : 람다 결과
run
val service = MultiportService("https://example.kotlinlang.org", 80)
val result = service.run {
port = 8080
query(prepareRequest() + " to port $port")
}
// let를 사용한 같은 코드 : 같은 결과 나온다
val letResult = service.let {
it.port = 8080
it.query(it.prepareRequest() + " to port ${it.port}")
}
- 객체를 생성하거나 사용하는 시점에서 다양한 작업을 수행시킨 후 결과를 반환받고 싶을 때 사용한다
- 참조 키워드 : this
- 리턴 타입 : 람다 결과
with
val numbers = mutableListOf("one", "two", "three")
val firstAndLast = with(numbers) {
"The first element is ${first()}," +
" the last element is ${last()}"
}
println(firstAndLast)
// The first element is one, the last element is three
- 반환된 결과를 사용할 필요가 없을 때 컨텍스트 객체에서 함수를 호출하는 데 사용한다
- extension function이 아니므로 객체를 인자로 받아 사용한다
- 참조 키워드 : this
- 리턴 타입 : 람다 결과
apply
val sxunea = Person("Sxunea").appy{
age = 32
city = "London"
}
println(sxunea)
// Person(name=Sxunea, age=32, city=London)
- 컨텍스트 객체 자체를 반환 하므로 값을 반환하지 않고 바로 사용하기 좋다
- 참조 키워드 : this
- 리턴 타입 : 객체 그자체
also
val people = listOf(
Person(
city = "London",
age = 28,
),
Person(
email = "Korea",
age = 55,
)
)
people.first()
.also { firstPerson ->
println("나이: ${firstPerson.age}")
}.functionAnything()
- 추가 작업을 함께 실행시키고 싶을 때 사용한다
- 참조 키워드 : it
- 리턴 타입 : 객체 그자체
따라서 스코프 함수의 사용 상황을 정리해보면 객체를 다시 반환해야하는지 / 참조시 네이밍이 필요한지 / extension function 인지 세가지로 크게 분류할 수 있겠다. 위의 예시를 보고 적절하게 판단하여 선택하는 것이 좋겠다.
또, 과한 스코프 함수의 사용은 과한 체이닝을 만들어서 가독성을 떨어뜨리기 때문에 적당히 사용해보자.
'코틀린 > Kotlin Lang' 카테고리의 다른 글
[Kotlin] 코틀린 함수 뽀개기 - (2) 람다와 고차함수 (0) | 2024.07.24 |
---|---|
[Kotlin] runCatching과 Result (0) | 2024.07.18 |
[Kotlin] Generic의 이해, in & out 키워드 (0) | 2024.07.06 |
[Kotlin] Data Class와 깊은복사, 얕은복사 (0) | 2024.07.06 |
[Koltin] 코틀린 Collection의 확장함수 (0) | 2024.03.06 |