Kotlin 언어에서 고차 함수인 apply, also, let 및 run은 객체의 체인 가능 구성 및 최소한의 보일러플레이트로 로컬 변경을 단순화하기 위해 등장했습니다. 이러한 함수는 가변 및 불변 객체 작업을 용이하게 하며, 변환 체인을 간결하게 표현할 수 있도록 하며 변수의 범위 문제를 일부 해결합니다.
이 함수들은 빌더 패턴과 유창한 인터페이스 접근 방식에서 유래되었습니다. 이들이 등장한 이유는 코드를 더 깔끔하게 만들고 불필요한 보조 변수를 선언하는 것을 피하기 위함입니다.
일반적인 접근 방식은 객체에 여러 번 접근하거나 임시 변수를 추출해야 합니다. 이는 가독성을 낮추고 오류 위험을 증가시킵니다:
val user = User() user.name = "Alex" user.age = 26 user.isActive = true
apply, also, let, run 함수를 사용하면 표현력이 높아집니다:
val user = User().apply { name = "Alex" age = 26 isActive = true }
간단한 설명:
data class User(var name: String = "", var age: Int = 0, var isActive: Boolean = false) val configuredUser = User().apply { name = "Alice" age = 30 isActive = true } debugUser(configuredUser.also { println("사용자가 구성되었습니다: $it") }) val emailLength = configuredUser.email?.let { it.length } ?: 0 val description = configuredUser.run { "$name ($age)" }
주요 특징:
let 함수는 작동하는 객체를 변경할 수 있습니까?
let 함수는 객체를 변경하기 위한 것이 아닙니다. 그것은 값에 변환을 적용하고 결과를 반환하는 데 사용됩니다. let 내부에서는 this 대신 it에 접근합니다.
val upperName = user.name.let { it.uppercase() } // let은 user를 변경하지 않습니다.
apply와 run의 차이점은 무엇인가요?
둘 다 람다 내에서 this와 작업하지만, 반환 값에서 차이가 있습니다:
// apply val building = StringBuilder().apply { append("start-") append("end") } // building은 StringBuilder입니다. // run val result = StringBuilder().run { append("start-") append("end") toString() } // result는 String입니다.
apply와 let을 중첩해서 사용할 수 있나요? 가능하다면, 언제 정당한가요?
네, nullable 작업 시 객체를 집계하거나 단계별로 구성할 때 중첩 사용이 부드럽게 권장됩니다:
val userInfo = user?.apply { isActive = true }?.let { "${it.name}이 활성화되었습니다: ${it.isActive}" }
코드의 모든 곳에서 let을 사용하여 객체를 수정하며, apply와 let이 혼합되어 결과적으로 객체가 변경되지 않으며 기대되는 값이 체인에서 손실됩니다.
장점:
단점:
apply와 also를 사용하여 설정 및 로깅하고, let은 nullable 작업 및 결과 획득만 사용하며, run은 새로운 값을 계산해야 하는 변환 체인에 사용합니다.
장점:
단점: