Android

[코틀린] apply, run, with, let, also?

Diane_KIM 2023. 11. 29. 20:35

Kotlin은 객체의 컨텍스트 내에서 코드 블록을 실행하는 것이 목적인 여러 함수가 포함되어 있습니다.

람다 표현식이 제공된 객체에서 이러한 함수를 호출하면 임시 범위가 형성되고, 이 범위에서는 이름 없이 객체에 액세스할 수 있습니다.

=> 이러한 함수를 범위 함수(스코프 함수)라고 합니다.

클래스에서 생성한 인스턴스를 스코프에 전달하면

인스턴스의 속성이나 함수를 좀 더 깔끔하게 불러 편하게 쓸 수 있는 방법

main함수와 별도의 scope에서 인스턴스의 변수와 함수를 조작하므로 코드가 깔끔

 

apply

참조 연산자 사용하지 X, 처리가 끝나면 인스턴스 반환

- 인스턴스를 생성한 후 변수에 담기 전에 '초기화 과정'을 수행할 때 많이 사용

- 수신객체의 프로퍼티만 사용하여 초기화한다

val peter = Person().apply {
    name = "Peter"
    age = 18
}
=============================
val clark = Person()
clark.name = "Clark"
clark.age = 18

 

 

run

참조 연산자를 사용하지 X, 처리가 끝나면 최종 값을 반환

- 어떤 값을 계산할 필요가 있거나 여러개의 지역 변수의 범위를 제한할 때

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

 

 

with

run과 동일하나 인스턴스를 참조연산자 대신 파라미터로 객체를 받는다는 차이만 있음

- non-nullable 수신 객체이고, 결과가 필요하지 않은 경우에만 사용

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

 

let

참조 연산자를 사용 (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)

 

also

참조 연산자를 사용 (it), 처리가 끝나면 인스턴스를 반환

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

- 객체의 사이드 이펙트 확인

- 객체에 프로퍼티에 데이터를 할당하기 전에 데이터의 유용성 검사

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