수신 객체 지정 람다 labda with receiver
수신 객체를 명시하지 않고 람다의 본문 안에서 다른 객체의 메소드를 호출할 수 있게 한다.
(=어떤 객체의 이름을 반복하지 않고, 그 객체에 대해 다양한 연산을 수행할 수 있다!)
수신 객체지정 람다 중 하나인, with 와 apply 에 대해 알아볼까요?
.1 with
문법
inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
receiver = 수신 객체, block = 수신 객체 지정 람다
수신 객체 지정 람다의 실행 결과를 반환합니다.
아래 결과가 나오는 코드를 3가지 방법으로 나열해 보면,
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Now I know the alphabet!
with 함수 적용 전,
fun alphabet(): String {
val result = StringBuilder()
for(letter in 'A'..'Z') {
result.append(letter)
}
result.append("\\\\nNow I know the alphabet!")
return result.toString()
}
//5.16 알파벳 만들기
with 함수 적용 후 - this 사용
fun alphabet() :String {
val stringBuilder = StringBuilder()
return with(stringBuilder) {
for(letter in 'A'..'Z') {
this.append(letter)
}
append("\\\\nNow I know the alphabet!")
this.toString()
}
}
//5.17 with 를 사용해 알파벳 만들기
with 함수 적용 후 - this 생략 & 식을 본문으로 하는 함수
fun alphabet() = with(StringBuilder()) {
for (letter in 'A'..'Z') {
append(letter)
}
append("\\nNow I know the alphabet!")
toString()
}
//5.18 with 와 식을 본문으로 하는 함수를 활용해 알파벳 만들기
수신 객체 지정 람다 VS 확장함수
확장 함수에서의 this - 그 함수가 확장하는 타입의 **인스턴스, .**this 생략 가능
메소드 이름 충돌
이름이 같은 메소드가
- with 에게 인자로 넘긴 객체의 클래스
- with 를 사용하는 코드가 들어있는 클래스 안에
에 있다면?
with 에게 인자로 넘긴 객체의 클래스 의 함수가 실행된다.
+) OuterClass 에 정의된 함수를 사용하고 싶다면? this 참조 앞에 레이블을 붙이면 됩니다.
class MethodNamingConflicts {
override fun toString(): String {
print("this is method in class")
return "this is method in class"
}
fun alphabet() :String {
val stringBuilder = StringBuilder()
return with(stringBuilder) {
for(letter in 'A'..'Z') {
append(letter)
}
append("\\\\nNow I know the alphabet!")
toString()
this@MethodNamingConflicts.toString()
}
}
}
this is method in classthis is method in class
.2 apply
문법
inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
block = 수신 객체 지정 람다
수신 객체를 반환합니다.
apply 적용 - 확장 함수로 정의
fun alphabet() = StringBuilder().apply {
for(letter in 'A'..'Z') {
append(letter)
}
append("\\nNow I know the alphabet!")
}.toString()
//5.19 apply 를 사용해 알파벳 만들기
언제 쓸까?
객체의 인스턴스를 만들면서 즉시 프로퍼티 중 일부를 초기화 해야 하는 경우
Java (라이브러리 내의) Builder 객체가 이런 역할 담당
Kotlin (라이브러리의 지원 없이) 그 클래스 인스턴스에 대해 apply 활용
fun createViewWithCustomAttributes(context: Context) {
TextView(context).apply {
text = "Sample Text"
textSize = 20.0f
setPadding(10, 0, 0, 0)
}
}
//5.20 apply 를 TextView 초기화에 사용하기
원하는대로 TextView 의 메소드를 호출 or 프로퍼티를 설정
buildString
수신객체지정람다만 인자로 받는다. (수신 객체 = 항상 StringBuilder)
fun alphabet() = buildString {
for(letter in 'A'..'Z') {
append(letter)
}
append("\\\\nNow I know the alphabet!")
}
//5.21 buildString 으로 알파벳 만들기
PREVIEW) chapter 11. DSL
영역 특화 연어 DSL Domain Specific Language
- 수신 객체 지정 람다를 DSL 정의에 사용하는 방법
- 수신 객체 지정 람다를 호출하는 함수를 직접 작성하는 방법
을 배운다고 합니다.
참고.
https://medium.com/@limgyumin/코틀린-의-apply-with-let-also-run-은-언제-사용하는가-4a517292df29
'Language > Kotlin' 카테고리의 다른 글
[Coroutine] 코루틴 사용하기 (0) | 2022.02.05 |
---|---|
[Coroutine] 코루틴이란? (0) | 2022.02.03 |
[KotlinInAction] 5장-람다로 프로그래밍(5) 수신 객체 지정 람다: with 와 apply (0) | 2021.12.08 |
[KotlinInAction] 5장-람다로 프로그래밍(1) 람다 식과 멤버 참조 (0) | 2021.11.24 |
[KotlinInAction] 3장-함수 정의와 호출(2)컬렉션처리, 문자열다루기, 코드 다듬기(로컬함수/확장) (0) | 2021.11.03 |