[코틀린] apply, run, with, let, also?
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)
}
}