Developing Myself Everyday
article thumbnail

πŸ“š λ²”μœ„ 지정 ν•¨μˆ˜λž€?


Kotlin의 ν‘œμ€€ λΌμ΄λΈŒλŸ¬λ¦¬μ—λŠ” 개체의 μ»¨ν…μŠ€νŠΈ λ‚΄μ—μ„œ μ½”λ“œ 블둝을 μ‹€ν–‰ν•˜λŠ” 것이 λͺ©μ μΈ μ—¬λŸ¬ λ²”μœ„ 지정 ν•¨μˆ˜λ“€μ΄ μžˆλ‹€. λžŒλ‹€ 식이 μžˆλŠ” κ°œμ²΄μ—μ„œ μ΄λŸ¬ν•œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ μž„μ‹œ λ²”μœ„κ°€ ν˜•μ„±λ˜κ³  이런 λ²”μœ„μ—μ„œλŠ” 이름 없이 객체에 μ•‘μ„ΈμŠ€ν•  수 μžˆλ‹€. μ΄λŸ¬ν•œ λ²”μœ„ ν•¨μˆ˜μ˜ μ’…λ₯˜λ‘œλŠ” let, run, with, apply, also의 λ‹€μ„― 가지가 μžˆλ‹€.

 

기본적으둜 λ²”μœ„ ν•¨μˆ˜λ“€μ€ λ™μΌν•œ λͺ©μ μ„ 가지고 μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€. λ‹€λ₯Έ 점은 이 κ°œμ²΄κ°€ 블둝 λ‚΄μ—μ„œ μ‚¬μš© κ°€λŠ₯ν•˜κ²Œ λ˜λŠ” 방식이 전체 ν‘œν˜„μ‹μ˜ 결과이닀. 이런 이유둜 ν•˜λ‚˜μ˜ λ²”μœ„ ν•¨μˆ˜λ₯Ό κ³ λ₯΄λŠ” 것은 νž˜λ“  일이닀. μ΄μ œλΆ€ν„° λ²”μœ„ κΈ°λŠ₯κ³Ό ν•΄λ‹Ή κ·œμΉ™μ˜ 차이점에 λŒ€ν•œ μžμ„Έν•œ μ„€λͺ…을 μ œκ³΅ν•˜κ² λ‹€.

 

 

 

λ²”μœ„ ν•¨μˆ˜ μš”μ•½

 

μœ„μ˜ ν…Œμ΄λΈ”μ€ λ²”μœ„ ν•¨μˆ˜μ˜ 차이점듀을 λ‚˜νƒ€λ‚Έ ν…Œμ΄λΈ”μ΄λ‹€. κ°€μž₯ λˆˆμ— λ„λŠ” 것은 Object referenceλŠ” itκ³Ό this둜 λ‚˜λ‰˜μ–΄μ Έ 있고 Return valueλŠ” Lambda result와 Context objectκ°€ μžˆλ‹€λŠ” 것이닀.

 

 

 

🀼‍♂️ λ²”μœ„ 지정 ν•¨μˆ˜λ“€μ„ κ΅¬λ³€ν•˜λŠ” 방법


λ²”μœ„ 지정 ν•¨μˆ˜μ˜ 차이λ₯Ό μ•„λŠ” 것은 각 상황에 μ–΄λ–€ λ²”μœ„ 지정 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•˜λŠ”μ§€ μ•„λŠ” κ°€μž₯ 쒋은 방법이닀. 각 λ²”μœ„ 지정 ν•¨μˆ˜λ“€κ°„μ—” μœ„μ—μ„œ λ³΄μ•˜λ“―μ΄ 2개의 차이가 μ‘΄μž¬ν•œλ‹€.

 

 1. Context Object (μ»¨ν…μŠ€νŠΈ 개체)λ₯Ό μ°Έμ‘°ν•˜λŠ” 방식

 2. λ°˜ν™˜ κ°’

 

 

Context Object (μ»¨ν…μŠ€νŠΈ 개체)λ₯Ό μ°Έμ‘°ν•˜λŠ” 방식

λ²”μœ„ 지정 ν•¨μˆ˜ λ‚΄μ—μ„œ μ»¨ν…μŠ€νŠΈ κ°œμ²΄λŠ” μ‹€μ œ 이름 λŒ€μ‹  짧은 참쑰둜 μ‚¬μš©ν•  수 μžˆλ‹€. 각 λ²”μœ„ 지정 ν•¨μˆ˜λŠ” μ»¨ν…μŠ€νŠΈ 개체λ₯Ό μ°Έμ‘°ν•˜κΈ° μœ„ν•΄ λžŒλ‹€ μˆ˜μ‹ μž(this) λ˜λŠ” λžŒλ‹€ 인수 (it) 두 가지 방법 쀑 ν•˜λ‚˜λ₯Ό μ‚¬μš©ν•œλ‹€. λ‘˜μ˜ κΈ°λŠ₯은 λ™μΌν•˜λ‹€.

 

fun main() {
    val str = "Hello"
    // this
    str.run {
        println("The string's length: $length")
        // thisλŠ” μƒλž΅ κ°€λŠ₯ν•˜λ‹€.
        //println("The string's length: ${this.length}") 
    }

    // it
    str.let {
        println("The string's length is ${it.length}")
    }
}

 

 

this

λŒ€λΆ€λΆ„μ˜ μƒν™©μ—μ„œ 'this'λŠ” μƒλž΅ κ°€λŠ₯ν•˜λ‹€. ν•˜μ§€λ§Œ 'this'λ₯Ό μƒλž΅ν•˜λ©΄ μˆ˜μ‹  멀버와 μ™ΈλΆ€ 객체λ₯Ό κ΅¬λΆ„ν•˜κΈ° μ–΄λ €μšΈ 수 μžˆλ‹€. λ”°λΌμ„œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ±°λ‚˜ 속성에 값을 ν• λ‹Ήν•˜μ—¬ μˆ˜μ‹  λ©€λ²„μ—κ²Œ μž‘λ™ν•˜λŠ” λžŒλ‹€μ˜ 경우 'this'λ₯Ό μƒλž΅ν•˜μ§€ μ•ŠλŠ” 것이 μ’‹λ‹€. run, with, applyκ°€ 'this'λ₯Ό μ‚¬μš©ν•΄ μ»¨ν…μŠ€νŠΈ 개체λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλ‹€.

 

it

'it'은 인수 이름이 μ§€μ •λ˜μ§€ μ•ŠλŠ” 경우 default 값을 'it'으둜 μ„€μ •ν•œλ‹€. ν•˜μ§€λ§Œ 개체의 ν•¨μˆ˜λ‚˜ 속성을 ν˜ΈμΆœν•  λ•Œ 'this'와 같이 μ•”μ‹œμ μœΌλ‘œ 개체λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€. λ”°λΌμ„œ 객체λ₯Ό ν•¨μ†Œ 호좜의 인수둜 주둜 μ‚¬μš©ν•  λ•ŒλŠ” 'it'을 톡해 μ»¨ν…μŠ€νŠΈ 객체에 μ ‘κ·Όν•˜λŠ” 것이 μ’‹λ‹€. μ½”λ“œ λΈ”λ‘μ—μ„œ μ—¬λŸ¬ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  λ•Œλ„ 'it'을 μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.  let, alsoκ°€ 'it'λ₯Ό μ‚¬μš©ν•΄ μ»¨ν…μŠ€νŠΈ 개체λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλ‹€.


 

 

λ°˜ν™˜ κ°’

λ²”μœ„ 지정 ν•¨μˆ˜λ“€μ΄ λ°˜ν™˜ν•˜λŠ” 값은 2κ°€μ§€λ‘œ λ‚˜λ‰œλ‹€. μ»¨ν…μŠ€νŠΈ κ°œμ²΄μ™€ λžŒλ‹€ 결과이닀. λ‹€μŒμ— μˆ˜ν–‰ν•  μž‘μ—…μ— 따라 μ›ν•˜λŠ” λ°˜ν™˜ 값을 μ‹ μ€‘ν•˜κ²Œ κ³ λ €ν•΄μ•Ό ν•˜λ©° μ΄λŠ” μ‚¬μš©ν•  μ΅œμƒμœ„ λ²”μœ„ κΈ°λŠ₯을 μ„ νƒν•˜λŠ”λ° 도움이 λœλ‹€.

 

 

Context object

apply와 also의 λ°˜ν™˜ 값은 μ»¨ν…μŠ€νŠΈ 객체 μžμ²΄μ΄λ‹€. λ”°λΌμ„œ 이듀은 λ™μΌν•œ 객체에 λŒ€ν•΄ 연이어 ν•¨μˆ˜ ν˜ΈμΆœμ„ 계속할 수 μžˆλ‹€.

 

val numberList = mutableListOf<Double>()
numberList.also { println("Populating the list") }
    .apply {
        add(2.71)
        add(3.14)
        add(1.0)
    }
    .also { println(it) }
    .also { println("Sorting the list") }
    .sort()

println(numberList)


κ²°κ³Ό
Populating the list
[2.71, 3.14, 1.0]
Sorting the list
[1.0, 2.71, 3.14]

 

 

Lambda result

let, run, withλŠ” λžŒλ‹€ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€. κ·Έλž˜μ„œ λ³€μˆ˜μ— κ²°κ³Όλ₯Ό ν• λ‹Ήν•˜κ±°λ‚˜ 결과에 λŒ€ν•œ μž‘μ—…μ„ μ—°κ²°ν•˜λŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ μ‚¬μš©ν•  수 μžˆλ‹€.

 

 

val numbers = mutableListOf("one", "two", "three")
val countEndsWithE = numbers.run { 
    add("four")
    add("five")
    count { it.endsWith("e") }
}
println("There are $countEndsWithE elements that end with e.")

 

 

 

🎈 λ²”μœ„ 지정 ν•¨μˆ˜


let

'let'은 'it'으둜 μ»¨νƒμŠ€νŠΈ 개체λ₯Ό μ°Έμ‘°ν•˜λ©° λžŒλ‹€ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€.

 

'let' 은 호좜 체인의 결과에 λŒ€ν•΄ ν•˜λ‚˜ μ΄μƒμ˜ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆλ‹€. μ•„λž˜μ˜ μ˜ˆμ‹œλŠ” String으둜 된 numbers λ¦¬μŠ€νŠΈμ—μ„œ λ¬Έμžμ—΄μ˜ 길이가 3 초과인 number만 좜λ ₯ν•˜λŠ” μ½”λ“œμ΄λ‹€. 

 

val numbers = mutableListOf("one", "two", "three", "four", "five")
val resultList = numbers.map { it.length }.filter { it > 3 }
println(resultList)

 

μœ„μ˜ μ½”λ“œμ˜ 단점은 λ°”λ‘œ 'resultList'λΌλŠ” λ³€μˆ˜κ°€ 였직 좜λ ₯을 μœ„ν•΄ μ‚¬μš©λ˜κ³  μžˆλ‹€λŠ” 것이닀. λ˜ν•œ 가독성 λ˜ν•œ 떨어진닀. 이제 'let'을 μ‚¬μš©ν•΄ 보겠닀.

 

val numbers = mutableListOf("one", "two", "three", "four", "five")
numbers.map { it.length }.filter { it > 3 }.let { 
    println(it)
}

 

우린 이제  'resultList'λΌλŠ” λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  κ²°κ³Όλ₯Ό 좜λ ₯ν•  수 μžˆλ‹€. 'let'의 κ°€μž₯ 큰 μž₯점은 λ°”λ‘œ null이 될 수 μžˆλŠ” 객체에 μ‚¬μš©ν•  수 μžˆλ‹€λŠ” 것이닀. 

 

val str: String? = "Hello"   
val length = str?.let { 
    println("let() called on $it")        
    it.length
}

 

μœ„μ˜ lengthλŠ” str이 null이 아닐 λ•Œλ§Œ 값이 ν• λ‹Ήλ˜κ²Œ λœλ‹€.

 

 

with

'with'은 'this'으둜 μ»¨νƒμŠ€νŠΈ 개체λ₯Ό μ°Έμ‘°ν•˜λ©° λžŒλ‹€ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€.

 

'with'은 λ‹€λ₯Έ λ²”μœ„ 지정 ν•¨μˆ˜λ“€κ³ΌλŠ” λ‹€λ₯Έ 점이 μžˆλ‹€. λ°”λ‘œ ν™•μž₯ ν•¨μˆ˜κ°€ μ•„λ‹ˆλΌλŠ” 것이닀. λ”°λΌμ„œ λ°˜ν™˜λœ κ²°κ³Όλ₯Ό μ‚¬μš©ν•  ν•„μš”κ°€ 없을 λ•Œ μ»¨ν…μŠ€νŠΈ 객체의 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κΈ° μœ„ν•΄ 'with'을 μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€. 

 

'with'은 "이 객체와 ν•¨κ»˜ λ‹€μŒ 행동을 μˆ˜ν–‰ν•œλ‹€" 둜 해석할 수 μžˆλ‹€.

 

val numbers = mutableListOf("one", "two", "three")
with(numbers) {
    println("'with' is called with argument $this")
    println("It contains $size elements")
}

 

 

run

'run'은 'this'으둜 μ»¨νƒμŠ€νŠΈ 개체λ₯Ό μ°Έμ‘°ν•˜λ©° λžŒλ‹€ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€.

 

'run'은 ν™•μž₯ ν•¨μˆ˜λ‘œ κ΅¬ν˜„λœ 'with'이라고 ν•  수 μžˆλ‹€. λ˜ν•œ 'run'은 λžŒλ‹€κ°€ 객체λ₯Ό μ΄ˆκΈ°ν™”ν•˜κ³  λ°˜ν™˜ 값을 κ³„μ‚°ν•˜λŠ” κ²½μš°μ— μœ μš©ν•˜λ‹€. λ”°λΌμ„œ 'run'을 μ‚¬μš©ν•˜λ©΄ μ΄ˆκΈ°ν™”μ™€ λ°˜ν™˜ 값을 λ™μ‹œμ— μˆ˜ν–‰ν•  수 μžˆλ‹€.

 

data class Person(val name: String, var age: Int)

fun main() {
    val person = Person("John", 30)

    person.run {
        println("Name: $name, Age: $age")

        age += 1
        println("Updated Age: $age")
    }
}

 

'run'은 λΉ„-ν™•μž₯ ν•¨μˆ˜λ‘œ μ‚¬μš©ν•  수 μžˆλ‹€. 'with'의 ν™•μž₯ ν•¨μˆ˜ 버전이 'run' 이기에 'run'을 λΉ„-ν™•μž₯ ν•¨μˆ˜λ‘œ μ‚¬μš©ν•˜λ©΄ 'with'이라고 생각할 수 μžˆμ§€λ§Œ, run은 λ”°λ‘œ μ»¨νƒμŠ€νŠΈ 객체λ₯Ό 가지지 μ•Šκ³  였직 λžŒλ‹€ κ²°κ³Όλ§Œμ„ λ°˜ν™˜ν•œλ‹€.

 

val message = "Hello, Kotlin!"

val result = run {
    val formattedMessage = message.toUpperCase()
    val reversedMessage = formattedMessage.reversed()
    "Final message: $reversedMessage"
}

println(result)

 

 

apply

'apply'은 'this'으둜 μ»¨νƒμŠ€νŠΈ 개체λ₯Ό μ°Έμ‘°ν•˜λ©° μ»¨ν…μŠ€νŠΈ 객체 자체λ₯Ό λ°˜ν™˜ν•œλ‹€.

 

'apply'λŠ” μ»¨ν…μŠ€νŠΈ 객체 자체λ₯Ό λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμ—, λ°˜ν™˜ 값을 갖지 μ•Šκ³  주둜 μˆ˜μ‹ μž 객체의 멀버에 μž‘μš©ν•˜λŠ” μ½”λ“œ 블둝에 μ‚¬μš©ν•˜λŠ” 것이 ꢌμž₯λœλ‹€. 'apply'의 객체λ₯Ό ꡬ성할 λ•Œ κ°€μž₯ 많이 μ‚¬μš©λœλ‹€.

 

'apply'λŠ” "λ‹€μŒ 할당을 객체에 μ μš©ν•œλ‹€"둜 해석할 수 μžˆλ‹€.

 

val adam = Person("Adam").apply {
    age = 32
    city = "London"        
}
println(adam)

 

 

also

'also'은 'it'으둜 μ»¨νƒμŠ€νŠΈ 개체λ₯Ό μ°Έμ‘°ν•˜λ©° μ»¨ν…μŠ€νŠΈ 객체 자체λ₯Ό λ°˜ν™˜ν•œλ‹€.

 

'also'λŠ” μ»¨ν…μŠ€νŠΈ 객체λ₯Ό 인수둜 λ°›μ•„ 일뢀 λ™μž‘μ„ μˆ˜ν–‰ν•˜λŠ” 데 μœ μš©ν•˜λ‹€. 'also'λ₯Ό μ‚¬μš©ν•˜μ—¬ μ†μ„±μ΄λ‚˜ ν•¨μˆ˜κ°€ μ•„λ‹Œ 객체에 λŒ€ν•œ μ°Έμ‘°κ°€ ν•„μš”ν•œ λ™μž‘μ΄λ‚˜ μ™ΈλΆ€ λ²”μœ„μ—μ„œμ˜ 'this' μ°Έμ‘°λ₯Ό κ°€λ €μ£Όκ³  싢지 μ•Šμ„ λ•Œ μ‚¬μš©ν•  수 μžˆλ‹€.

 

 'also'λŠ” "그리고 λ˜ν•œ 객체와 ν•¨κ»˜ λ‹€μŒμ„ μˆ˜ν–‰ν•œλ‹€"둜 해석할 수 μžˆλ‹€.

 

 

 

Reference

 

Scope functions | Kotlin

 

kotlinlang.org

 

profile

Developing Myself Everyday

@λ°°μ€€ν˜•

ν¬μŠ€νŒ…μ΄ μ’‹μ•˜λ‹€λ©΄ "μ’‹μ•„μš”β€οΈ" λ˜λŠ” "κ΅¬λ…πŸ‘πŸ»" ν•΄μ£Όμ„Έμš”!