함수들의 개념 확인용으로 작성 및 다른분의 블로그의 내용을 토대로 작성되었습니다.
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
https://kotlinlang.org/docs/reference/scope-functions.html#run