본문 바로가기

Android/Kotlin

kotlin(코틀린) apply,run,with,let,also 함수

함수들의 개념 확인용으로 작성 및 다른분의 블로그의 내용을 토대로 작성되었습니다.

 

 

5가지 함수의 정의

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
    • run과 유사하나 사용 방법이 다름
    • ex) with(object)
    • 사용규칙
      • Null이 될수 없는 수신 객체이고 결과가 필요하지 않은경우에만 사용
val person: Person = getPerson()
with(person) {
    print(name)
    print(age)
}

//동일코드
val person: Person = getPerson()
print(person.name)
print(person.age)
  • also
    • 사용규칙
      • 수신 객체 람다가 전달된 수신 객체를 전혀 사용 하지 않거나 수신 객체의 속성을 변경하지 않고 사용하는 경우 also 를 사용
      • 클래스에서 init 코드와 동일시 작동이 되므로 데이터 확인 등 과 같은 형태로 활용하기 좋음
class Book(author: Person) {
    val author = author.also {
      requireNotNull(it.age)
      print(it.name)
    }
}

//동일코드
class Book(val author: Person) {
    init {
      requireNotNull(author.age)
      print(author.name)
    }
}
  • apply
    • 생성과 동시에 호출하여 사용
    • 사용 규칙
      • 수신 객체 람다 내부에서 수신 객체의 함수를 사용하지 않고 수신 객체 자신을 다시 반환 하려는 경우에 apply 를 사용
      • return this => apply를 사용하는 객체를 전달
val peter = Person().apply {
    // apply 의 블록 에서는 오직 프로퍼티 만 사용합니다!
    name = "Peter"
    age = 18
}

//동일코드
val peter = Person()
peter.name = "peter"
peter.age = 18
  •  run
    • 이미 생성된 메서드나 객체를 호출하여 사용
    • 객체가 null 가능성도 있기 때문에 null체크 사용을 같이 하는편이 좋음
    • 객체의 메서드나 필드를 연속적으로 사용할 때
    • 사용규칙
      • 어떤 값을 계산할 필요가 있거나 여러개의 지역 변수의 범위를 제한하려면 run 을 사용
      • 매개 변수로 전달된 명시적 수신객체 를 암시적 수신 객체로 변환 할때 run ()을 사용
val inserted: Boolean = run {
    // person 과 personDao 의 범위를 제한 합니다.
    val person: Person = getPerson()
    val personDao: PersonDao = getPersonDao()
    // 수행 결과를 반환 합니다.
    personDao.insert(person)
}
fun printAge(person: Person) = person.run {
    // person 을 수신객체로 변환하여 age 값을 사용합니다.
    print(age)
}


//동일코드
val person: Person = getPerson()
val personDao: PersonDao = getPersonDao()
val inserted: Boolean = personDao.insert(person)
fun printAge(person: Person) = {
    print(person.age)
}
  • let
val alice = Person("Alice", 20, "Amsterdam")
println(alice)
alice.moveTo("London")
alice.incrementAge()
println(alice)

//위에 코드를 let을 통하여 변경가능
Person("Alice", 20, "Amsterdam").let {
    println(it)
    it.moveTo("London")
    it.incrementAge()
    println(it)
}
  • 사용규칙
    • 지정된 값이 null 이 아닌 경우에 코드를 실행해야 하는 경우
    • Nullable 객체를 다른 Nullable 객체로 변환하는 경우
    • 단일 지역 변수의 범위를 제한 하는 경우
getNullablePerson()?.let {
    // null 이 아닐때만 실행됩니다.
    promote(it)
}
val driversLicence: Licence? = getNullablePerson()?.let {
    // nullable personal객체를 nullable driversLicence 객체로 변경합니다.
    licenceService.getDriversLicence(it) 
}
val person: Person = getPerson()
getPersonDao().let { dao -> 
    // 변수 dao 의 범위는 이 블록 안 으로 제한 됩니다.
    dao.insert(person)
}

//동일 코드
val person: Person? = getPromotablePerson()
if (person != null) {
  promote(person)
}
val driver: Person? = getDriver()
val driversLicence: Licence? = if (driver == null) null else
    licenceService.getDriversLicence(it)
val person: Person = getPerson()
val personDao: PersonDao = getPersonDao()
personDao.insert(person)

 

 

 

 

 

 

 

- 참고자료

 

https://black-jin0427.tistory.com/169

 

[Android, Kotlin] 코틀린의 run, with, apply, let, also 정리

안녕하세요. 블랙집입니다. 그동안 코틀린을 사용하면서 run, with, apply, let, also 를 사용했지만 내용을 한번 정리해 보면 좋을 것 같아 간략히 포스팅을 합니다. this run , with , and apply refer to the c..

black-jin0427.tistory.com

https://medium.com/@limgyumin/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%9D%98-apply-with-let-also-run-%EC%9D%80-%EC%96%B8%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EA%B0%80-4a517292df29

 

코틀린 의 apply, with, let, also, run 은 언제 사용하는가?

원문 : “Kotlin Scoping Functions apply vs. with, let, also, and run”

medium.com

https://kotlinlang.org/docs/reference/scope-functions.html#run

 

Scope Functions - Kotlin Programming Language

 

kotlinlang.org