안드로이드

Kotlin apply, with, let, also, run 사용?

코딩하는후운 2021. 5. 11. 13:47
반응형

범위 지정 함수는 무엇을 하는가?

이 5가지 함수는 기본적으로 매우 비슷한 기능을 합니다.

이 함수들은 두가지 구성 요소를 가집니다.

 

with, also, apply, let, run 은 아래의 3 가지 차이점 중 1 가지가 서로 다릅니다.

  • 범위 지정 함수 의 호출시에 수신 객체가 매개 변수로 명시적으로 전달되거나 수신 객체의 확장 함수로 암시적 수신 객체 로 전달된다.
  • 범위 지정 함수 의 수신 객체 지정 람다 에 전달되는 수신 객체가 명시적 매개 변수 로 전달 되거나 수신 객체의 확장 함수로 암시적 수신 객체로 코드 블록 내부로 전달 된다.
  • 범위 지정 함수의 결과로 수신 객체를 그대로 반환하거나 수신 객체 지정 람다 의 실행 결과를 반환한다.

 

apply, with, let, also, run 은 언제 사용해야 하는가?

apply 사용 규칙

수신 객체 람다 내부에서 수신 객체의 함수를 사용하지 않고 수신 객체 자신을 다시 반환 하려는 경우에 apply 를 사용합니다.

수신 객체 의 프로퍼티 만을 사용하는 대표적인 경우가 객체의 초기화 이며, 이곳에 apply 를 사용합니다.

 

val peter = Person().apply {
  // apply 의 블록 에서는 오직 프로퍼티 만 사용합니다!
  name = "Peter"
  age
= 18
}

 

 

also 사용 규칙

수신 객체 람다가 전달된 수신 객체를 전혀 사용 하지 않거나 수신 객체의 속성을 변경하지 않고 사용하는 경우 also 를 사용합니다.

also 는 apply 와 마찬가지로 수신 객체를 반환 하므로 블록 함수가 다른 값을 반환 해야하는 경우에는 also 를 사용할수 없습니다.

 

class Book(author: Person) {
  val author = author.also {
    requireNotNull(it.age)
    print(it.name)
  }
}

 

let 사용 규칙

다음과 같은 경우에 let 을 사용합니다.

  • 지정된 값이 null 이 아닌 경우에 코드를 실행해야 하는 경우.
  • Nullable 객체를 다른 Nullable 객체로 변환하는 경우.
  • 단일 지역 변수의 범위를 제한 하는 경우.

getNullablePerson()?.let {
  // null 이 아닐때만 실행됩니다.
  promote(it)
}

val driversLicence: Licence? = getNullablePerson()?.let {
  // nullable personal객체를 nullable driversLicence 객체로 변경합니다.
  licenceService.getDriversLicence(it)
}

 

with 사용 규칙

Non-nullable (Null 이 될수 없는) 수신 객체 이고 결과가 필요하지 않은 경우에만 with 를 사용합니다.

 

val person: Person = getPerson()
with(person) {
  print(name)
  print(age)
}

 

run 사용 규칙

어떤 값을 계산할 필요가 있거나 여러개의 지역 변수의 범위를 제한하려면 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)
}

 

 

하나의 코드 블록 내에서 여러 범위 지정 함수를 중첩 하려는 경우가 종종 있습니다. 그러나 범위 지정 함수가 중첩되면 코드의 가독성이 떨어지고 파악하기 어려워 집니다.

 

원칙적으로 중첩은 하지 않는 것이 좋습니다.

수신객체 지정 람다 에 수신 객체가 암시적으로 전달되는 apply, run, with 는 중첩하지 마십시오.

이 함수들은 수신 객체를 this 또는 생략하여 사용하며, 수신객체의 이름을 다르게 지정할수 없기 때문에 중첩될 경우 혼동 하기 쉬워집니다.

 

also 와 let 을 중첩 해야만 할때는 암시적 수신 객체 를 가르키는 매개 변수 인 it 을 사용하지 마십시오. 대신 명시적인 이름을 제공하여 코드 상의 이름이 혼동되지 않도록 해야 합니다.

 

----

 

범위 지정 함수를 호출 체인에 결합 할 수 있습니다.

중첩 과는 달리 범위 지정 기능을 호출 체인에 결합하면 코드의 가독성이 향상됩니다.

호출 체인에서 범위 지정 함수를 결합하는 예 를 살펴 보겠습니다.

 

private fun insert(user: User) = SqlBuilder().apply {
    append("INSERT INTO user (email, name, age) VALUES ")
    append("(?", user.email)
    append(",?", user.name)
    append(",?)", user.age)
}.also {
    print("Executing SQL update: $it.")
}.run {
    jdbc
.update(this) > 0
}

 

 

 

 

참조 :

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

 

반응형

'안드로이드' 카테고리의 다른 글

Storage Scope  (0) 2021.05.14
ViewBinding  (0) 2021.05.13
Android 멀티 모듈  (0) 2021.05.11
Wildcard(*) import 방지  (0) 2021.05.03
Gradle Dependency 관리하기 (buildSrc)  (0) 2021.04.02