코틀린의 스코프 함수(“범위 함수”)는 객체의 코드 블록 실행 맥락을 관리할 수 있도록 하는 표준 함수(let, also, run, apply, with)입니다. 이들은 다음과 같은 점에서 다릅니다:
it 또는 this를 통해.| 함수 | this/it | 반환 | 용도 |
|---|---|---|---|
| let | it | 결과 | 체인 작업, nullable 작업, 매핑 |
| also | it | 객체 | 부작용, 로깅, 디버그 |
| run | this | 결과 | 계산, 반환과 함께 초기화 |
| apply | this | 객체 | 객체 구성, 빌더 |
| with | this | 결과 | 외부 API 작업, 외부 객체 사용 |
예시:
let: nullable 객체에 편리함:val str: String? = "Text" str?.let { println(it.length) }
apply: 객체 설정:val paint = Paint().apply { color = Color.RED strokeWidth = 2f }
run: 객체에서 실행하고 결과 반환:val length = "abcde".run { length }
with: 외부 객체 작업:val sb = StringBuilder() with(sb) { append("Hello, ") append("world!") toString() }
also: 부작용을 위한 것 (예: 로깅):val list = mutableListOf(1, 2, 3) list.also { println("Before: $it") }.add(4)
it에서 객체의 복사본을 생성하므로, 객체 속성을 변경하기가 그리 편리하지 않습니다.this / it)를 반환하므로, 빌더에 유용합니다.with는 일반 함수이며, 확장 함수가 아닙니다.let과 also의 차이점은 무엇인가요?
답변:
it를 사용합니다,let은 람다의 결과를 반환하며, 종종 변환 체인에 사용됩니다,also는 원래 객체를 반환하며, 부작용(로깅, 디버그 등)을 위해 사용되어 변환 체인에 영향을 미치지 않습니다.예시:
val result = listOf(1).also { println(it) }.map { it * 2 } // 결과 — List<Int>
이야기
초심자는 객체를 "체인"에서 설정하기 위해 let을 사용하여, 설정 블록 종료 후 결과로 람다를 받아 객체가 아닌 결과값을 받았습니다(예: 아무것도 아님) 때문에 DSL 구축 과정이 깨졌습니다.
이야기
nullable 객체를 다루는 코드 작성을 할 때, let 대신 run을 사용하여 반환 값의 차이를 인식하지 못했습니다. 결국 표현식의 결과가 예상과 달라지고, null이 나타나는 등 애플리케이션의 논리가 깨졌습니다.
이야기
큰 빌더에서 우연히 내부 객체에 대해 with를 사용하여 확장 패턴에 기대했습니다. with는 확장 함수가 아니기 때문에 여러 with 블록 체인이 올바르게 작동하지 않았고, 내부 호출이 혼동되어 현 객체의 경계를 넘어갔습니다. 객체 생성 계층을 완전히 다시 작성해야 했습니다.