ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kotlin] Scope functions (let, with, run, apply, also) ์ดํ•ด
    Android/Kotlin 2021. 11. 8. 01:10
    ๋ฐ˜์‘ํ˜•

    Scope functions ์ด๋ž€?

      ์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•˜๋ฉด์„œ ์—ฌ๋Ÿฌ Scope function๋“ค์„ ์‚ฌ์šฉํ•˜์˜€์ง€๋งŒ, ์‚ฌ์šฉํ•˜๋ฉด์„œ๋„ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ์˜๊ตฌ์‹ฌ์ด ๋“ค ๋•Œ๋„ ๋งŽ์•˜๊ณ  ์ƒํ™ฉ์— ๋”ฐ๋ผ ์–ด๋–ค Scope function๋“ค์„ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ข‹์„์ง€ ๊ณ ๋ฏผ์ด ๋งŽ์•˜์Šต๋‹ˆ๋‹ค. ๊ณต์‹๋ฌธ์„œ๋ฅผ ๋ณด๊ณ  ์ œ๋Œ€๋กœ ๊ณต๋ถ€ํ•˜๊ธฐ๋กœ ๋งˆ์Œ์„ ๋จน์—ˆ๊ณ  ๊ณต์‹๋ฌธ์„œ๋ฅผ ํ† ๋Œ€๋กœ ๊ฐœ๋ฐœ ๊ฒฝํ—˜๊ณผ ํ•จ๊ป˜ ๊ธ€์„ ์ž‘์„ฑํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
      ๋จผ์ €, Scope function์€ 5๊ฐœ๋กœ let, with, run,apply, also ๊ฐ€ ์ฝ”ํ‹€๋ฆฐ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Scope function์€ ๋ง ๊ทธ๋Œ€๋กœ ๋ฒ”์œ„(Scope)๊ฐ€ ์ƒ๊ธฐ๋Š”๋ฐ ํ•ด๋‹น ๋ฒ”์œ„๋Š” ํŠน์ • ๊ฐ์ฒด์˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์ผ๋ จ์˜ ๋™์ž‘์„ ํฌํ•จํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. Scope function์€ ๋žŒ๋‹ค์‹๊ณผ ๋™์ผํ•˜๊ฒŒ ์ž‘์„ฑ์„ ํ•˜๋ฉฐ, ์ธ์Šคํ„ด์Šค์— ํ•ด๋‹นํ•˜๋Š” ๋ณ€์ˆ˜ ์—†์ด ๋‚ด๋ถ€ ๋ณ€์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

     

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

      ํ•ด๋‹น ์ฝ”๋“œ๋Š” Scope function์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋กœ ๊ฐ์ฒด๋ฅผ ํŠน์ • ๋ณ€์ˆ˜์— ๋Œ€์ž…์„ ํ•œ ํ›„ ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ๋ฉ”์†Œ๋“œ๋“ค์„ ํ˜ธ์ถœํ•˜๋Š” ๋ชจ์Šต๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

     

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

      ๋‹ค์Œ์€ Scope function ์ค‘ ํ•˜๋‚˜์ธ let ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋น„๊ต๋Š” ์•„๋ž˜์—์„œ ํ•˜๊ฒ ์ง€๋งŒ Scope function์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์„ ๋•Œ๋ณด๋‹ค ๊ฐ€๋…์„ฑ์ด ์žˆ์œผ๋ฉฐ, ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋“ค์„ ์ƒ์„ฑํ•˜๊ณ  ํ•ด๋‹น ๋ณ€์ˆ˜๋“ค๋กœ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒŒ ์•„๋‹Œ it ์ด๋ผ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

     

    Scope function ๋น„๊ต

      ๊ฐ Scope function๋“ค์„ ์„œ์ˆ ํ•˜๊ธฐ ์ „์— ๊ณตํ†ต์ ์ด ๋ฌด์—‡์ด๊ณ , ์ฐจ์ด์ ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ ์–ด๋–ค ์ ์„ ์ง‘์ค‘์ ์œผ๋กœ ํ™•์ธํ•˜๋ฉด ๋˜๋Š”์ง€ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ผ๋‹จ Scope function์€ ํŠน์ • ๊ฐ์ฒด์˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ง€๋Š” ๋ฒ”์œ„(Scope)๋ฅผ ์ƒ์„ฑํ•˜์—ฌ  ๋ฒ”์œ„ ๋‚ด์˜ ์ฝ”๋“œ๋“ค์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๊ณตํ†ต์ ์ธ ๋ชฉ์ ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ•จ์ˆ˜๋“ค๋งˆ๋‹ค ์ฐจ์ด๊ฐ€ ์กฐ๊ธˆ์”ฉ ์กด์žฌํ•˜๋Š”๋ฐ ์ฒซ ๋ฒˆ์งธ๋กœ๋Š” ๋ฒ”์œ„ ๋‚ด์—์„œ ๊ฐ์ฒด์˜ ์ปจํ…์ŠคํŠธ๋ฅผ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ Scope function์˜ ๋ฐ˜ํ™˜๊ฐ’์—์„œ ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. 2๊ฐ€์ง€ ์ฐจ์ด์ ์„ ์ค‘์ ์œผ๋กœ ๊ฐ ํ•จ์ˆ˜๋“ค์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘์„ ํ•˜๊ณ  ํ™œ์šฉ๋˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค.

     

    let

    /**
     * Calls the specified function [block] with `this` value as its argument and returns its result.
     *
     * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#let).
     */
    @kotlin.internal.InlineOnly
    public inline fun <T, R> T.let(block: (T) -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return block(this)
    }

      ๋‹ค์Œ์€ let ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. let์€ T ๋ผ๋Š” Generic ๊ฐ์ฒด์˜ ํ™•์žฅํ•จ์ˆ˜๋กœ ์ •์˜๋˜์–ด ์žˆ์œผ๋ฉฐ block ์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„์„œ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. block ํ•จ์ˆ˜๋Š” T ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๊ณ  R์„ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ •์˜๋กœ๋งŒ ๋ณด๋ฉด ์ •ํ™•ํ•˜๊ฒŒ ์•Œ๊ธฐ ์–ด๋ ค์›Œ์„œ ์˜ˆ์ œ์™€ ๊ฐ™์ด ์„ค๋ช…ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

     

    val numbers = mutableListOf("one", "two", "three", "four", "five")
    numbers.map { it.length }.filter { it > 3 }.let { 
        println(it)
        // and more function calls if needed
    }

      Kotlin ๊ณต์‹ ๋ฌธ์„œ์˜ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ let ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „๊นŒ์ง€ ์ฝ”๋“œ๋ฅผ ์„ค๋ช…ํ•˜์ž๋ฉด numbers์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ map ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๋ฅผ ๋‹ด๋Š” ๋ฆฌ์ŠคํŠธ {3,3,5,4,4} ๋กœ ๋ณ€ํ˜•ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ดํ›„ filter ํ•จ์ˆ˜๋กœ ๊ฐ’์ด 3 ์ด์ƒ์œผ๋กœ๋งŒ ํ•„ํ„ฐ๋งํ•˜๊ฒŒ ๋˜์–ด {5,4,4} ๋กœ ๋ณ€ํ˜•๋ฉ๋‹ˆ๋‹ค. 

     let ํ•จ์ˆ˜์—์„œ ๋žŒ๋‹คํ‘œํ˜„์‹์œผ๋กœ ํ‘œํ˜„์ด ๋œ ์‹์ด block ํ•จ์ˆ˜๊ฐ€ ๋˜๊ณ  T ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋ฆฌ์ŠคํŠธ๊ฐ€ ํ•ด๋‹น์ด ๋˜๊ณ  R์€ ๋งˆ์ง€๋ง‰ ์ฝ”๋“œ์ธ println์˜ ๋ฆฌํ„ด๊ฐ’์ธ Unit์ด ๋ฉ๋‹ˆ๋‹ค. block ํ•จ์ˆ˜์—์„œ ๋ฆฌ์ŠคํŠธ ์ปจํ…์ŠคํŠธ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” it ์ด๋ผ๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ฉฐ ์ปค์Šคํ…€ํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    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
    }

     ๋˜ํ•œ  let์€ ์ฃผ๋กœ non-null ๋ณ€์ˆ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ null check์™€ ๋™์‹œ์— ์›ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ?. ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ null์ด๋ฉด ์‹คํ–‰ํ•˜์ง€ ์•Š๋„๋ก ํ•˜๊ณ  null์ด ์•„๋‹ˆ๋ฉด let ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•˜์—ฌ null check๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  ์ € ๋˜ํ•œ let ํ•จ์ˆ˜๋Š” ๋Œ€๋ถ€๋ถ„ null checkํ•˜๋ฉด์„œ non-null์ด๋ฉด ํŠน์ • ๋ฉ”์†Œ๋“œ๋“ค์„ ์‹คํ–‰ํ•˜๋„๋ก ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 

     

    ์ •๋ฆฌ๋ฅผ ํ•˜์ž๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    • Scope ๋‚ด์—์„œ ํ•ด๋‹น ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” it ์ด๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ์‚ฌ์šฉ, ์ปค์Šคํ…€ํ•˜๊ฒŒ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
    • ๋ฐ˜ํ™˜ ๊ฐ’์€ block ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ๊ฐ’
    • null check์™€ ํ•จ๊ป˜ block ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

     

    with

    /**
     * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
     *
     * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#with).
     */
    @kotlin.internal.InlineOnly
    public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return receiver.block()
    }

      ๋‹ค์Œ์€ with ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. with์€ let๊ณผ ๋‹ค๋ฅด๊ฒŒ ํ™•์žฅํ•จ์ˆ˜๋กœ ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š๊ณ  T ์™€ block ํ•จ์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. block ํ•จ์ˆ˜๋Š” T ์ปจํ…์ŠคํŠธ ๋‚ด์— ์ •์˜๋œ ํ•จ์ˆ˜๋กœ R์„ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ๋ถ€๊ฐ€ ์„ค๋ช…์„ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

     

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

      ์ฃผ๋กœ with ํ•จ์ˆ˜๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์„ ํŠน์ • ๋ณ€์ˆ˜์— ๋Œ€์ž…ํ•˜์ง€ ์•Š๊ณ  ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋Œ€์ž…๋œ T ์ปจํ…์ŠคํŠธ ๋‚ด์˜ ๋ฉ”์†Œ๋“œ๋“ค์ด ์—ฐ์†์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ๋Š” numbers๊ฐ€ T ์— ํ•ด๋‹น๋˜๊ณ , block ํ•จ์ˆ˜๋Š” ๋žŒ๋‹คํ‘œํ˜„์‹์œผ๋กœ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•˜์—ฌ ๋ธ”๋Ÿญ ๋‚ด์— ์—ฌ๋Ÿฌ ๋ฉ”์†Œ๋“œ๋“ค์ด ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. block์€ ํ•ด๋‹น ๊ฐ์ฒด ์ปจํ…์ŠคํŠธ๋ฅผ this๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ณ , ๊ทธ์™ธ ๋ฉค๋ฒ„๋ณ€์ˆ˜ ๋˜๋Š” ๋ฉ”์†Œ๋“œ๋“ค์€ ์ง์ ‘ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

     

    val numbers = mutableListOf("one", "two", "three")
    val firstAndLast = with(numbers) {
        "The first element is ${first()}," +
        " the last element is ${last()}"
    }
    println(firstAndLast)

      ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ๋Š” ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„ ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. numbers๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ first์™€ last์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ๋ฌธ์ž์—ด์„ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

     

    ์ •๋ฆฌ๋ฅผ ํ•˜์ž๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    • Scope ๋‚ด์—์„œ ํ•ด๋‹น ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” this ์ง์ ‘ ์‚ฌ์šฉ
    • ๋ฐ˜ํ™˜ ๊ฐ’์€ block ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ๊ฐ’
    • T ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„ ํ•ด๋‹น ์ปจํ…์ŠคํŠธ ๋‚ด์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ์—ฐ์†์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š”๋ฐ ์ฃผ๋กœ ์‚ฌ์šฉ

     

    run

    /**
     * Calls the specified function [block] with `this` value as its receiver and returns its result.
     *
     * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#run).
     */
    @kotlin.internal.InlineOnly
    public inline fun <T, R> T.run(block: T.() -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return block()
    }

     ๋‹ค์Œ์€ run ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. with๊ณผ ๋น„์Šทํ•˜๊ฒŒ block ํ•จ์ˆ˜๊ฐ€ T ์ปจํ…์ŠคํŠธ ๋‚ด์— ์ •์˜๋œ ํ•จ์ˆ˜๋กœ block์˜ ๋ฆฌํ„ด๊ฐ’์ด R๋กœ ๋ฐ˜ํ™˜์ด ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ run ํ•จ์ˆ˜๋Š” let๊ณผ ๋™์ผํ•˜๊ฒŒ T ์˜ ํ™•์žฅํ•จ์ˆ˜๋กœ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. 

     

    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}")
    }

     run ํ•จ์ˆ˜๋Š” ์ฃผ๋กœ ๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”์™€ ๋™์‹œ์— ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋ฆฌํ„ด๊ฐ’์œผ๋กœ ํ•„์š”ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. run ํ•จ์ˆ˜์—์„œ๋Š” T ์ปจํ…์ŠคํŠธ๋ฅผ this๋กœ ์ง์ ‘ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋ฉค๋ฒ„๋ณ€์ˆ˜, ๋ฉ”์†Œ๋“œ ๋˜ํ•œ ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, run์€ ํ™•์žฅ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ with๊ณผ ๊ฐ™์ด ๊ฐ์ฒด์˜ ์ปจํ…์ŠคํŠธ ์—†์ด ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด ๋•Œ๋Š” ๋‚ด๋ถ€์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ์‹คํ–‰ ํ›„ ๋ฐ˜ํ™˜๊ฐ’์„ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ๋งŒ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋กœ ์˜ˆ์ œ๋กœ ๋‹ค๋ฃจ์ง„ ์•Š๊ณ  kotlin ๊ณต์‹ ๋ฌธ์„œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    ์ •๋ฆฌ๋ฅผ ํ•˜์ž๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    • Scope ๋‚ด์—์„œ ํ•ด๋‹น ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” this ์ง์ ‘ ์‚ฌ์šฉ
    • ๋ฐ˜ํ™˜ ๊ฐ’์€ block ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ๊ฐ’
    • ๊ฐ์ฒด์˜ ์ดˆ๊ธฐํ™”์™€ ๋™์‹œ์— ๋ฐ˜ํ™˜ ๊ฐ’์ด ํ•„์š”ํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ

     

    apply

    /**
     * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
     *
     * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#apply).
     */
    @kotlin.internal.InlineOnly
    public inline fun <T> T.apply(block: T.() -> Unit): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        block()
        return this
    }

      ๋‹ค์Œ์€ apply ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ์œ„์—์„œ ์„ค๋ช…ํ•œ let, with, run๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ block ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์€ ์—†์Šต๋‹ˆ๋‹ค. apply ํ•จ์ˆ˜๋Š” block ํ•จ์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ T ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ์›ํ•˜๋Š” ๋™์ž‘์„ ํ•œ ํ›„ T ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. 

     

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

      apply๊ฐ€ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ๋ฐ˜ํ™˜ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ๋กœ ๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. builder ํŒจํ„ด๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ apply ํ•จ์ˆ˜๋กœ ๋ฉค๋ฒ„๋ณ€์ˆ˜๋“ค์„ ์ดˆ๊ธฐํ™”ํ•œ ํ›„ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋กœ ํŠน์ • ๋ณ€์ˆ˜์— ๋Œ€์ž…ํ•˜๊ฑฐ๋‚˜ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์—ฐ์†์ ์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. this๋กœ T ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

     

    ์ •๋ฆฌ๋ฅผ ํ•˜์ž๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    • Scope ๋‚ด์—์„œ ํ•ด๋‹น ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” this ์ง์ ‘ ์‚ฌ์šฉ
    • ๋ฐ˜ํ™˜ ๊ฐ’์€ ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด 
    • ์ฃผ๋กœ ๊ฐ์ฒด์˜ ์ดˆ๊ธฐํ™”ํ• ๋•Œ ์‚ฌ์šฉ

     

    also

    /**
     * Calls the specified function [block] with `this` value as its argument and returns `this` value.
     *
     * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#also).
     */
    @kotlin.internal.InlineOnly
    @SinceKotlin("1.1")
    public inline fun <T> T.also(block: (T) -> Unit): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        block(this)
        return this
    }

      ๋‹ค์Œ์€ also ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. also๋Š” T ์˜ ํ™•์žฅํ•จ์ˆ˜๋กœ ์ •์˜๋˜์–ด ์žˆ์œผ๋ฉฐ block ํ•จ์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. apply์™€ ๋™์ผํ•˜๊ฒŒ block ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ๊ฐ’์ด ์—†์œผ๋ฉฐ ์›ํ•˜๋Š” ๋™์ž‘ ํ›„ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

     

    val numbers = mutableListOf("one", "two", "three")
    numbers
        .also { println("The list elements before adding new one: $it") }
        .add("four")

      also๋Š” T ์— ํ•ด๋‹นํ•˜๋Š” ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„ ์›ํ•˜๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”๋Š” apply ๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ๊ทธ ์™ธ ๋ถ€๊ฐ€์ ์ธ ์ž‘์—…์€ also ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ๋Š” also ํ•จ์ˆ˜๋กœ ์›ํ•˜๋Š” ๋ฌธ์ž์—ด์„ ์ถœ๋ ฅ์„ ํ•œ ํ›„ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ๋ฐ˜ํ™˜ํ•˜์—ฌ add ํ•˜๋„๋ก ์ž‘์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

     

    ์ •๋ฆฌ๋ฅผ ํ•˜์ž๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    • Scope ๋‚ด์—์„œ ํ•ด๋‹น ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” it ์ด๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ์‚ฌ์šฉ, ์ปค์Šคํ…€ํ•˜๊ฒŒ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
    • ๋ฐ˜ํ™˜ ๊ฐ’์€ ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด
    • ๊ฐ์ฒด์˜ ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์„ ํ•  ๋•Œ ์‚ฌ์šฉ

     

     

    ์ •๋ฆฌ

    https://kotlinlang.org/docs/scope-functions.html#function-selection

     5๊ฐ€์ง€์˜ Scope function์„ ์ •๋ฆฌํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ ๋ฐฉ์‹๊ณผ ๋ฐ˜ํ™˜ ๊ฐ’์ด ๋‹ค๋ฅด๊ณ  ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ํ™•์žฅํ•จ์ˆ˜๋กœ ์ •์˜๋˜๊ฑฐ๋‚˜ ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ํ•จ์ˆ˜๋กœ ์ •์˜๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ํฐ ์ฐจ์ด์ž…๋‹ˆ๋‹ค.

     

     

     

     

    ์ฐธ๊ณ 

     

    Scope functions | Kotlin

     

    kotlinlang.org

     

    ๋ฐ˜์‘ํ˜•

    'Android > Kotlin' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

    [Kotlin] Set ์‚ฌ์šฉ๋ฒ•  (0) 2021.08.13
    [Kotlin] Map ์‚ฌ์šฉ๋ฒ•  (0) 2021.08.12
    [Kotlin] List ์‚ฌ์šฉ๋ฒ•  (0) 2021.08.12
    [Kotlin] String ์‚ฌ์šฉ๋ฒ•  (0) 2021.08.12
    [Kotlin] Array ์‚ฌ์šฉ๋ฒ•  (0) 2021.08.12
Designed by Tistory.