본문 바로가기
Android(Kotlin)

[Kotlin Android] Scope Function

by 클리마 2024. 3. 26.
728x90

이번 포스팅은 Kotlin의 Scope Function에 대한 개념을 간단하게 알아보고, Android에서 Scope Function을 사용하는 패턴에 대해 알아보겠습니다.



개념


  • 이름을 사용하지 않고도 객체에 액세스할 수 있는 임시 스코프 생성 함수.
  • 코드를 더 간결하고 가독성있게 만들기 위해 존재.
  • inline function으로 런타임 오버헤드를 줄일 수 있음.

종류


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

let

  • 수행했던 결과 값이 리턴된다.
  • 람다식의 수행결과가 중요할 때 사용
  • 주로 nullable 변수의 값이 null이 아닐 경우 동작을 정의할 때 사용
val str: String? = "Hello"   
//processNonNullString(str)       // compilation error: str can be null
val length = str?.let { 
    println("let() called on $it")        
    processNonNullString(it)      // OK: 'it' is not null inside '?.let { }'
    it.length
}

run

  • 일반함수
  • 주로 객체 구성과 결과 계산이 한번에 있을 때 사용
// 객체 구성과 결과 계산을 한 번에 할 때
val service = MultiportService("https://example.kotlinlang.org", 80)

val result = service.run {
    port = 8080
    query(prepareRequest() + " to port $port")
}

// the same code written with let() function:
val letResult = service.let {
    it.port = 8080
    it.query(it.prepareRequest() + " to port ${it.port}")
}
// 코드 블록을 실행하고 결과를 계산하는 고차 함수를 만들 때
val hexNumberRegex = run {
    val digits = "0-9"
    val hexDigits = "A-Fa-f"
    val sign = "+-"

    Regex("[$sign]?[$digits$hexDigits]+")
}

for (match in hexNumberRegex.findAll("+123 -FFFF !%*& 88 XYZ")) {
    println(match.value)
}
// 별도로 함수를 실행시켜야 할 때
data.language?.let { language ->
    languageText.isVisible = true
    languageText.text = language
} ?: kotlin.run {
    languageText.isGone = true
    languageText.text = ""
}

with

  • 확장함수
  • 다른 스코프 함수들과 달리 Nullable 지원은 존재하지 않는다.
  • 주로 객체를 통해 무엇을 할 수 있는지 보여줄 때 사용
// 특정 객체가 계속 사용될 경우 활용한다.
fun initViews() = with(binding) {
    // 해당 스코프에서 binding.textView로 호출할 필요 X
    textView.text = ""
}

apply

  • 주로 객체 초기화에 사용
val adam = Person("Adam").apply {
    age = 32
    city = "London"        
}
println(adam)

also

  • 주로 객체 유효성이나 디버깅의 용도로 사용
  • 객체가 매개변수로 전달이 된다 → 매개변수를 따로 선언하지 않으면 it으로 접근가능
fun getRandomInt(): Int = Random.nextInt(100).also {
    writeToLog("getRandomInt() generated value $it")
}
728x90