코틀린 표준 라이브러리에서 제공하는 Scope Functions 있습니다. 지금부터 Scope Functions 에 대해 알아보고,  각각 어떻게 활용하는지 예시를 통해서 확인하려고 합니다.   1. Scope Functions 개요 Scope fun...

[안드로이드] Scope functions(let, run, apply, also) 활용


코틀린 표준 라이브러리에서 제공하는 Scope Functions 있습니다.

지금부터 Scope Functions 에 대해 알아보고, 

각각 어떻게 활용하는지 예시를 통해서 확인하려고 합니다.



 


1. Scope Functions 개요

Scope function 은 어떤 객체에 대한 코드 블록을 만들고 실행시킵니다. 

이때, 블록 내 객체에 접근하기 쉬우며 특정 값을 return 하기도 한다는 특징을 가집니다.

대표적인 함수로 let, run, apply, also 가 있습니다.





2. Scope Functions 왜 사용해야 될까요?

Scope Function 이 가지는 특징은 바로 코드의 간결성과 가독성으로 이어집니다.

Scope Functions 을 사용했을 때와 사용하지 않은 예시를 통해 바로 확인해보겠습니다.


 (1) Scope Function 사용 안 했을 때

val alice = Person("Alice", 20, "Amsterdam")
alice.moveTo("London")
alice.incrementAge()


 (2) Scope Function 사용했을 때

Scope function let 을 통해서 person 객체에 대한 코드 블록을 만들어주고

전달 받은 it(person) 을 통해 쉽게 객체에 접근하는 것을 확인할 수 있습니다. 

Person("Alice", 20, "Amsterdam").let {
it.moveTo("London")
it.incrementAge()
}

결과적으로 특정 객체에 대한 코드블록은 가독성을 높여줄 수 있고,

객체 접근이 쉽기 때문에 반복적으로 객체를 적어줄필요가 없어 간결성 가집니다.




혹시 코드의 간결성에 대해 공감이 안 되셨나요?
막상 코드가 짧아진것 같지는 않은데 말이죠..
저는 특정 객체의 이름이 길다고했을 때, 
또는 객체를 조작(사용) 해야되는 경우가 많다고 가정하면
간결성 도움이 되는게 맞다고 긍정적으로 생각합니다:)
(저 또한 공식문서를 읽을 때 간결성에서 흠칫했기 때문에 부연설명 남겨요ㅎㅎ)


 


3. Scope Functions 활용

이제 Scope Functions 을 어떻게 활용해야 할지 고민이 필요합니다.

이들은 매우 유사한 기능을 가지고 있기 때문에 각각의 차이점을 인지하는게 중요한데요,

대표적으로 let, run, apply, also 각각 함수별로 객체 참조 방법, 리턴값, 예시 를 살펴보려고 합니다.


 ♣ let

 - 객체 참조 방법 : it

 - 리턴값 : lamda result

 - 예시 : 코드블록 내에서 참조되는 객체를 non-null 값으로 만들때 (safe operator=?. 를 계속 호출하지 않아도됨)

private fun printlnPersonInformation(person: Person?) {
var nameLength: Int?

// sope function 사용 안함
println(person?.name)
println(person?.age)
println(person?.location)
nameLength = person?.name?.length
println(nameLength)

// let 사용 (return 사용O)
nameLength = person?.let {
println(it.name)
println(it.age)
println(it.location)
it.name.length
}
println(nameLength)

// let 사용 (return 사용X)
person?.let {
println(it.name)
println(it.age)
println(it.location)
println(it.name.length)
}
}



 ♣ run

 - 객체 참조 방법 : this

 - 리턴값 : lamda result

 - 예시 : 특정 객체에 대한 작업(process) 을 담고, 필요한 결과 뽑을 때

val numbers = mutableListOf("one", "two", "three")
var countEndsWithE: Int

// scope function 사용 안함
numbers.add("four")
numbers.add("five")
countEndsWithE = numbers.count { it.endsWith("e") }
println("There are $countEndsWithE elements that end with e.")

// run 사용
countEndsWithE = numbers.run {
add("four")
add("five")
count { it.endsWith("e") }
}
println("There are $countEndsWithE elements that end with e.")



 ♣ apply

 - 객체 참조 방법 : this

 - 리턴값 : context object

 - 예시 : 객체 초기화할 때

var persons: ArrayList<Person> = ArrayList()

// scope function 사용 안함
persons.add(Person("Alice", 20, "Amsterdam"))
persons.add(Person("adam", 30, "London"))
println(persons)

// apply 사용
persons = ArrayList<Person>().apply {
add(Person("Alice", 20, "Amsterdam"))
add(Person("adam", 30, "London"))
}
println(persons)



 ♣ also

 - 객체 참조 방법 : it

 - 리턴값 : context object

 - 예시 : 부가작업이 필요할 때

// Scope function 사용 안함 
val value = Random().nextInt(100)
println("getRandomInt() generated value $value")

// also 사용
Random().nextInt(100).also {
println("getRandomInt() generated value $it")
}





끝으로...

scope function 을 정리하면서 각 함수마다 유사한 기능을 가지고 있어

어떻게 이해하고 설명해야될까 고민이 많았던 것 같습니다.

공식문서랑 몇몇 블로그를 참조하여 이해하기 쉬운 예시를 만드는 부분에 집중한 것 같습니다.

끝까지 읽어주셔서 감사합니다:)




참고자료

코틀린 공식문서

안드로이드 뉴토피아 (블로그)

developer88 (블로그)



0 comments: