본문 바로가기
코틀린

코틀린 확장함수 Scope함수 apply, with, let, also, run 이란?

by 기계공학 주인장 2023. 1. 16.
반응형

Scope함수 apply, with, let, also, run 사용방법

  • 각 Scope 함수들의 내부 모습(apply와 with 차이도 설명)
  • 사용 및 응용 예시
  • Scope 함수를 사용할 때 주의 사항

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


표준 확장함수들(Scope 함수)의 내부 모습

inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    return receiver.block()
}

inline fun <T> T.also(block: (T) -> Unit): T {
    block(this)
    return this
}

inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}

inline fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}

inline fun <T, R> T.run(block: T.() -> R): R {
    return block()
}

각각의 확장함수의 차이를 표로 표현

with

내부 형태

inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    return receiver.block()
}
  • with은 확장 함수로 사용되지 않는다
  • 대신 T를 받아서 매개변수에서 T라고 확실히 넘겨주기 때문에 명시적 수신 객체 이다.
    • 그렇기 때문에 this 나 it을 사용하지 않는다
  • 반환할 때는 T의 확장함수로 암시적 으로 전달하여 반환하며 block을 실행한 receiver를 반환한다.
  • 즉, 적용한 객체를 반환한다

apply

내부 형태

inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}
  • also는 확장 함수로 사용된다
  • 수신자를 암시적으로 (this)전달한다
  • 반환은 적용된 객체 자체(this)를 반환한다

let

내부 형태

inline fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}
  • 확장 함수이며 명시적 수신 객체(it)를 파라미터로 넘겨준다
  • block을 실행한 결과를 반환한다.

also

내부 형태

inline fun <T> T.also(block: (T) -> Unit): T {
    block(this)
    return this
}
  • 확장 함수이며 명시적 수신 객체(it)를 파라미터로 넘겨준다
    • 이 부분이 apply와 가장 큰 차이점
  • 그렇기 때문에 this를 사용하여 객체를 지정할 수 있다
  • 반환은 확장한 객체 자체 반환해준다

run

내부 형태

inline fun <T, R> T.run(block: T.() -> R): R {
    return block()
}
  • 수신자를 암시적으로 (this)전달한다
  • block을 실행한 결과를 반환한다
    • 본래 객체에 아무런 영향이 없다
    • 이 부분이 apply와 다른점이다

apply, with, let, also, run 각 사용 방법

apply

  • 확장 하여 지정하고 그 결과를 사용하고 싶을 때 사용한다
fun main() {
  val me = Person().apply {
    name = "Nishant"
    age = 19
    gender = 'M'
  }
  println(me)
}

 

with

  • apply와 거의 같은 용도로 사용한다
fun main() {
  val me = with(Person()) {
    name = "Nishant"
    age = 19
    gender = 'M'
  }
  println(me)
}

 

let

  • 해당 값을 다수의 장소에 사용할 때 좋다
  • ?:(엘비스 연산자)를 이용하여 nullPointCheck에도 사용할 수 있다
fun main() {
  val age = readLine()?.toIntOrNull()

  age?.let {
    println("You are $it years old");
  } ?: println("Wrong input!");
}

 

also

  • 적용한 값을 한정된 장소( { } )에서 사용하고 싶을 때 좋다
fun main() {
  Person(
    name = "Nishant",
    age = 19,
    gender = 'M'
  ).also { println(it) }
}

 

run

  • let과 비슷하지만 it으로 하나씩 지정하기 싫을 때 좋다
  • 즉, 해당 값의 내부 값을 다수의 장소에 사용할 때 좋다
fun main() {
  val me = Person(
    name = "Nishant",
    age = 19,
    gender = 'M'
  )
  me.run {
    println("My name is $name and I am $age years old.");
  }
}

Scope함수 apply, with, let, also, run 정리

정리하자면 다음과 같다

  • apply
    • 확장 하여 지정하고 그 결과를 사용하고 싶을 때 사용한다
  • with
    • 내부는 다르지만 apply와 거의 같은 용도로 사용한다
  • let
    • 해당 값을 다수의 장소에 사용할 때 좋다
    • ?:(엘비스 연산자)를 이용하여 nullPointCheck에도 사용할 수 있다
  • also
    • 적용한 값을 한정된 장소( { } )에서 사용하고 싶을 때 좋다
  • run
    • let과 비슷하지만 it으로 하나씩 지정하기 싫을 때 좋다
    • 즉, 해당 값의 내부 값을 다수의 장소에 사용할 때 좋다
반응형


"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


댓글