null
을 체크하는 로직을 리팩터링할 수 있다.fun printPerson(person: Person?) {
if (person != null) {
println(person.name)
println(person.age)
}
}
// scope function 사용 코드
fun printPerson(person: Person?) {
persln?.let {
println(it.name)
println(it.age)
}
}
let
: 확장함수. 람다를 받아, 람다 결과를 반환한다.
it
을 통해 대상 객체(Person
)에 접근할 수 있다.inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
let
, run
, also
apply
, with
let
, run
은 람다의 결과를 반환also
, apply
는 객체 그 자체를 반환let
, also
는 람다에서 수신 객체 호출 시 it
을 사용run
, apply
는 람다에서 수신 객체 호출 시 this
를 사용it 사용 | this 사용 | |
---|---|---|
람다의 결과 반환 | let | run |
객체 자체 반환 | also | apply |
val value1 = person.let { it.age } // age 반환
val value2 = person.run { this.age } // age 반환
val value3 = person.also { it.age } // Person 반환
val value4 = person.apply { this.age } // Person 반환
it
, this
차이점
it
: 생략이 불가능한 대신 다른 이름을 붙일 수 있다.this
: 생략 가능한 대신 다른 이름을 붙일 수 없다val value1 = person.let { p -> p.age }
val value2 = person.run { age }
let
, also
는 일반 함수를 받고 run
, apply
는 확장 함수를 받는다.
this
로 호출하고 생략할 수 있다.with
는 확장함수가 아니고 아래처럼 사용할 수 있다.
with(파미라터, 람다)
: this
로 접근하고 this
는 생략 가능val person = Person("does", 27)
with(person) {
println(name)
println(this.name)
}
val strings = listOf("apple", "car")
strings.map { it.length }
.filter { it > 3 }
.let(::println) // { lengths -> println(lengths) }
val length = str?.let {
println(it.uppercase())
it.length
}
val person = Person("does", 27).run(personRepository::save)
apply
특징: 객체 그 자체가 반환된다.// 모종의 이유로 Person 생성자에 hobby는 초기에 받지 않고
// 나중에 추가적으로 입력하는 경우가 있을 수 있다.
// 테스트 픽스처 설정 시 한 번에 넣어주고 싶을 때 사용 가능
fun createPerson(
name: String,
age: Int,
hobby: String
): Person {
return Person(
name = name,
age = age,
).apply {
this.hobby = hobby
}
}
also
특징 : 객체 그 자체가 반환된다.mutableListOf("one", "two", "three")
.also { println("four 추가 이전 지금 값 : $it") }
.add("four")
toClass
함수를 만들기 어려울 때return with(person) {
PersonDto( // this를 생략할 수 있어 필드가 많아도 코드가 간결해진다.
name = name,
age = age
)
}
// 1번 코드
if (person != null && person.isAdult) {
view.showPerson(person)
} else {
view.showError()
}
// 2번 코드
person?.takeIf { it.isAdult }
?.let(view::showPerson)
?: view.showError()