코틀린(Kotlin)

코틀린 Scope Functions - [ let, run, with, apply, also ]

알통몬_ 2019. 7. 16. 12:16
반응형


공감 및 댓글은 포스팅 하는데

 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 

도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 

만들어 나가겠습니다^^

 


오랜만에 코틀린을 공부하네요.


이번 코틀린 공부는 Scope Functions 입니다.


코틀린 공식 문서에서는 범위 함수에 대해 아래처럼 설명합니다.

The Kotlin standard library contains several functions whose sole purpose is to execute a block of code within the context of an object. 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. Such functions are called scope functions. There are five of them: letrunwithapply, and also.


여기서 사용된 모든 예제는 main() {}

메인 함수 블록 안에서 실행되었습니다.


일반적인 범위함수 사용 예제)

User 라는 Data class 가 있을 때

data class User(var name : String, var age: Int, var country: String) {

fun rename(newName: String) {
this.name = newName;
}

fun migration(country: String) {
this.country = country
}

fun nextYears() {
this.age += 1
}

}
User("박성균", 28, "한국").let {
println(it)
it.migration("미국")
it.nextYears()
it.rename("박이레")
print(it)
}

Main에서 실행했을 때 결과

범위 함수를 사용하지 않고 같은 결과를 얻기얻으려면 아래처럼 코드를 작성하겠죠?

val sunggyun  = User("박성균", 28, "한국")
println(sunggyun)

sunggyun.migration("미국")
sunggyun.nextYears()
sunggyun.rename("박이레")
print(sunggyun)

범위 함수는 새로운 기술을 소개하는 건 아니지만, 우리의 코드를 더 간결하고

가독성있게 만들어 줍니다.

위 예제만 보더라도 반복되는 sunggyun을 빼고 it 이라는 간단한 단어로 대체했죠?


스코프 함수들의 차이

스코프 함수들을 제목처럼 5가지가 있습니다. 이 함수들은 본질적으로 굉장히 서로

비슷하기 때문에 각 함수들의 차이를 이해하는 것이 스코프 함수를 공부하고

사용하는데 있어서 가장 중요하다고 할 수 있습니다.

함수들의 차이

- Context object를 타나내는 방법

- 반환 값

======================================================


Context object : this or it

스코프 함수의 람다 안에서는 실제 이름 대신에 짧게 줄여서 context object를

나타낼 수 있습니다. 각각의 스코프 함수들은 두 방법 중에 하나를 사용하는데요.

lambda receiver(this)를 사용하거나 lambda argument(it)을 사용합니다.

둘 다 같은 기능을 제공하기 때문에 두 기능의 장단점을 알아야 그 때 그때

더 좋은 방법을 사용할 수 있겠죠?

간단한 예제)

fun main() {

val str = "Hello world"

str.run {
println("recevier ex : str length = $length")
}
str.let {
println("recevier ex : str length = ${it.length}")
}

}

실행 결과는 같지만 사용 방법에 있어서 약간 다르죠?


this

: run, with, apply 

위 세 범위함수에서 context object를 lambda receiver로 나타냅니다.

키워드는 우리가 다 잘아는 this입니다.

때문에 람다 안에서 객체를 일반적인 클래스의 함수처럼 사용할 수 있습니다 .

대부분의 경우에서 this 키워드를 생략하고 receiver object의 멤버에 접근할 수

있습니다. 코드가 짧아지겠죠?

대신에 이렇게 this 를 생략하면 외부의 멤버나 변수와 receiver object의 멤버의

이름이 같을 경우에 혼동될 수도 있겠죠?

때문에 this를 생략하지않고 사용하는 것을 권장합니다.

예제)

data class Users(var name : String, var age: Int = 0, var country: String = "")

fun main() {

val thomas = Users("알통몬").apply {
age = 30 // same as this.age
country = "키르키즈스탄" // same as this.country
}

}


it

: let, also

위 두 범위함수에서 context object 를 lambda argument로 가집니다.

argument에 특별히 이름이 지정되어 있지 않다면 'it' 이 default name이 됩니다.

it 키워드는 this 보다도 짧고, 가독성도 좋습니다. 하지만 객체함수나 프로퍼티를

호출할 때 this 처럼 암시적으로 호출할 object가 없기 때문에 object 가 함수 호출에서

argument 로 사용될 때 유용합니다.

그리고 코들 블록에서 여러 변수를 사용한다면 it이 더 좋습니다.

it 예제)

fun main() {

fun getRandNumber() : Int{
return Random.nextInt(100).also {
println("gen num = $it")
}
}

val randInt = getRandNumber()


}


추가적으로 it 대신에 다른 이름을 넣어줄수도 있습니다.

fun main() {

fun getRandNumber() : Int{
return Random.nextInt(100).also {value ->
println("gen num = $value")
}
}

val randInt = getRandNumber()


}

물론 실행결과는 동일힙니다.


Return Value ( 반환 값)


- apply 와 also 는 context object를 반환합니다.

예제)

val scoreList = mutableListOf<Int>()
scoreList.also {
println("Populating the list")
}.apply {
add(100)
add(83)
add(95)
}.also {
println("Sorting the list")
}.sort()

println(scoreList)



- let, run, with 는 lambda 의 result를 반환합니다.

예제)

val numStrs = mutableListOf("Three", "Six", "Nine")

val countEndsWithE = numStrs.run {
add("Four")
add("Five")
count {
it.endsWith("e")
}
}
println("$countEndsWithE 개의 요소는 e로 끝난다.")

=======================================================

여기까지 Scope Functions에 대해 알아보았는데요.

포스팅이 길어져서 다음 포스팅으로 넘어갑니다.

다음 포스팅에서는  위에서 간단히 알아본 다섯 가지의 범의 함수에 대해

하나하나씩 알아보겠습니다.



반응형