Scope function
- 객체의 이름을 사용하지 않고, 객체에 접근이 가능하게 하는 함수
- 특정 객체에 대한 작업을 블록 안에 넣어 실행할 수 있도록 하는 함수 (feat. kotlinworld)
Function | Object reference | Return value | Is extension function |
let | it | Lambda result | Yes |
run | this | Lambda result | Yes |
run | - | Lambda result | No: called without the context object |
with | this | Lambda result | No: takes the context object as an argument |
apply | this | Object reference | Yes |
also | it | Object reference | Yes |
it
- 람다식 내부에서 사용되는 암시적 변수
- 람다식에서 인자가 하나인 경우 it 을 사용해서 인자를 참조할 수 있다.
this
- 클래스의 인스턴스를 참조하는데 사용된다.
- this 를 사용하여 클래스 내부에서 멤버 변수나 멤버 함수를 참조할 수 있다.
let
inline fun <T, R> T.let(block: (T) -> R): R
- 확장 함수이므로, 객체를 생성해서 할당하기 전에 사용이 가능하다.
- 인자로 Lambda function 을 받기 때문에 곧바로 Lambda function 에 해당하는 코드 블록을 작성할 수 있다.
- Lambda function 에 인자를 명시적으로 전달하기 때문에 인자를 it 이나 다른 이름을 부여해 참조가 가능하다.
- 반환 값이 Lambda Result 이다. 임의로 생성한 값이나 객체를 반환할 수 있다.
- 객체를 생성하거나 사용하는 시점에서 다양한 작업을 수행시킨 후 결과를 반환받고 싶을 때, 명시적인 네이밍이 필요할 때 유용하다.
val firstPerson = Person(
email = "firstPerson@gmail.com",
age = 28,
)
val secondPerson = Person(
email = "secondPerson@email.com",
age = 58,
)
val people = listOf(firstPerson, secondPerson)
val firstPersonEmailDoubleLength = people.first()
.let { firstPerson ->
val secondPerson = Person(
email = "wow@wow.com",
age = 10,
)
firstPerson.email.length * 2
}
- mutable 변수의 null check 를 진행하고 싶을 때 유용하다.
private var str: String? = null
fun process() {
if (str != null) {
println(str?.length)
}
}
private var str: String? = null
fun process() {
str?.let { println(it.length) }
}
- nullable 체이닝을 끊어내고 싶을 때 유용하다.
fun process(string: String?): List? {
return string?.asIterable()?.distinct()?.sorted()
}
@Nullable
public final List process(@Nullable String string) {
List var2;
if (string != null) {
Iterable var10000 = StringsKt.asIterable(
(CharSequence)string);
if (var10000 != null) {
var2 = CollectionsKt.distinct(var10000);
if (var2 != null) {
var2 = CollectionsKt.sorted((Iterable)var2);
return var2;
}
}
}
var2 = null;
return var2;
}
fun process(string: String?): List? {
return string?.let {
it.asIterable().distinct().sorted()
}
}
@Nullable
public final List process(@Nullable String string) {
List var10000;
if (string != null) {
int var4 = false;
var10000 = CollectionsKt.sorted(
(Iterable)CollectionsKt.distinct(
StringsKt.asIterable((CharSequence)string)));
} else {
var10000 = null;
}
return var10000;
}
- var4
- 추가 변수
- 초당 수천 번 호출되는 루프에선 문제가 될 수도 있다.
- null check 를 진행한다. if 블럭 내부에서 non null 로 auto-cast 되기 때문에 추가적으로 null check 를 진행할 필요도 없다.
- boolean 은 그다지 비용이 큰 자료형이 아니며 kotlin proguard 를 사용하는 경우 자동으로 제거된다는 의견도 있다.
run
inline fun <R> run(block: () -> R): R
inline fun <T, R> T.run(block: T.() -> R): R
- 단일 lambda function 을 인자로 받는 버전과 확장 함수로 이루어진 버전이 있다.
- 인자로 Lambda function 을 받기 때문에 곧바로 Lambda function 에 해당하는 코드 블록을 작성할 수 있다.
- with 와 유사하지만, run 은 확장 함수 버전 때문에 객체를 생성해서 할당하기 전에 사용이 가능하다는 차이가 생긴다.
- 두 경우 모두 반환 값이 Lambda Result 이다. 임의로 생성한 값이나 객체를 반환할 수 있다.
- 객체를 생성하거나 사용하는 시점에서 다양한 작업을 수행시킨 후 결과를 반환받고 싶을 때 유용하다.
val nameDoubleLength = Person.withDefaultName()
.run { name.length * 2 }
with
inline fun <T, R> with(receiver: T, block: T.() -> R): R
- 확장 함수가 아니다. 객체를 인자로 전달받아 사용한다.
- 두 번째 인자로 람다 함수를 받기 때문에 곧바로 Lambda function 에 해당하는 코드 블록을 작성할 수 있다.
- Lambda function 은 확장 함수 형태로 코드 블록 내에 수신 객체가 암시적으로 전달된다. this 를 이용해 참조한다.
- 반환 값이 Lambda Result 이다. 임의로 생성한 값이나 객체를 반환할 수 있다.
- 이미 생성된 객체에 일괄적인 작업을 처리할 때 유용하다.
val result = with(person) {
isCool = true
isAwesome = true
koreanName = “현구막"
"nice"
}
apply
inline fun <T> T.apply(block: T.() -> Unit): T
- 확장 함수이므로, 객체를 생성해서 할당하기 전에 사용이 가능하다.
- 인자로 Lambda function 을 받기 때문에 곧바로 Lambda function 에 해당하는 코드 블록을 작성할 수 있다.
- Lambda function 은 확장 함수 형태로 코드 블록 내에 수신 객체가 암시적으로 전달된다. this 를 이용해 참조한다.
- 반환 값이 Object reference 이다. 코드 블록 내에 전달된 수신객체를 그대로 다시 반환한다.
- 코드 블록이 모두 수행된 후 인스턴스가 할당되기 때문에 객체 생성시점에서 초기화를 할 때 유용하다.
val person = Person(
email = "aaa@gmail.com",
age = 28,
).apply { name = "홍길동" }
also
inline fun <T> T.also(block: (T) -> Unit): T
- 확장 함수이므로, 객체를 생성해서 할당하기 전에 사용이 가능하다.
- 인자로 Lambda function 을 받기 때문에 곧바로 Lambda function 에 해당하는 코드 블록을 작성할 수 있다.
- Lambda function 에 인자를 명시적으로 전달하기 때문에 인자를 it 이나 다른 이름을 부여해 참조가 가능하다.
- 반환 값이 Object reference 이다. 코드 블록 내에 전달된 수신객체를 그대로 다시 반환한다.
- 이름 그대로 객체에게 명령을 내리기 직전에 추가적인(also) 작업을 함께 수행시키고 싶을 때 유용하다.
val people = listOf(
Person(
email = "firstPerson@gmail.com",
age = 28,
),
Person(
email = "secondPerson@email.com",
age = 58,
)
)
people.first()
.also { firstPerson ->
println("이메일 길이: ${firstPerson.email.length}")
println("현재 나이: ${firstPerson.age}")
}.increaseAge()
Kotlin Scope function 올바르게 사용하기
let, also 와 같은 Scope function 을 오래전부터 사용해왔지만 정확히 어떤 상황에 어떤 Scope function 을 사용하면 좋을지 감이 잘 안잡혔다. 그러다 최근 Scope function 관련 질문도 받았었겠다, 각각의 Scop
hyeon9mak.github.io
코틀린 it과 this 정확히 무슨 개념일까?
항상 간편하게 사용했지만 정확히 알지 못했던 it과 this의 개념을 정리해봤습니다. it it은 람다식 내부에서 사용되는 암시적 변수입니다. 람다식에서 인자가 하나인 경우 it을 사용해서 인자를
like-while.tistory.com
'안드로이드 > Kotlin' 카테고리의 다른 글
[Kotlin] 객체 선언(Object Declaration) , 동반 객체(Companion Object) (0) | 2024.12.09 |
---|---|
[Kotlin] 타입 연산자(is, as), 널 처리 연산자 (0) | 2024.12.08 |
[Kotlin] Kotlin 이란 (0) | 2024.12.08 |