스코프 함수
- 객체의 컨텍스트 내에서 코드 블록을 실행 할 수 있게하는 함수
- 특정 객체에 대하여 임시로 이름 없이 작업을 수행할 때 유용
대표적인 스코프 함수
함수명 | 수신 객체 이름 | 반환값 | 주사용 목적 |
let | it | 람다 결과값 | null 체크, 임시 변수 범위 제한, 체이닝 |
run | this | 람다 결과값 | 객체 구성 + 결과 반환 |
with | this | 람다 결과값 | 외부 객체 구성 (확장 X) |
apply | this | 객체 자기 자신 | 객체 구성 (초기화 등) |
also | it | 객체 자기 자신 | 부수 작업 수행 (로깅, 디버깅 등) |
주요 스코프 함수 예시
let
- null 체크
- 임시 변수 범위 제한
val name: String? = "희우"
name?.let {
println("이름은 ${it} 입니다.") // null이 아닐 경우 실행
}
run
- 객체 구성
- 최종 결과 리텅
val textLength = "희우입니다.".run{
println("문자열 길이는 ${length}")
length
}
with
- 외부 객체를 인자로 전달
val sb = StrinbBuilder()
val result = with(sb) {
append("안녕")
append(" Kotlin")
toString()
}
apply
- 객체 구성 후 자기 자신 반환
val user = User("희우", 24).apply{
age += 1
}
also
- 디버깅, 로그 등 부수 효과
val list = mutableListOf("A", "B").also{
pritnln("초기 리스트: $it")
it.add("C")
}
문제
1. let을 사용하여 null 체크와 출력이 동시에 되도록 코드를 구현하시오.
답:
val name: String? = "희우"
// name이 null이 아니면 "이름은 희우입니다." 출력
name?.let{
println("이름은 $it입니다.")
}
2. 변수 input이 빈 문자열이 아니라면 길이를 출력하는 코드를 run을 사용해 작성하시오.
[조건]
- run을 반드시 사용
- 빈 문자열이면 아무 것도 출력하지 않아야함
답:
val input = "Hello"
// input이 빈 문자열이 아니면, "입력의 길이: 5" 출력
input.run{
println("입력의 길이: ${this.length}")
}
보충:
- 빈 문자열일 경우가 빠짐
input.takeIf { it.isNotEmpty() }?.run{
println("입력의 길이: ${length}")
}
3. 다음 User 클래스는 이름과 나이를 저장하는 데이터 클래스이다.
data class User(var name: String, var age: Int)
아래 코드의 빈칸을 채워 새로운 User 인스턴스를 만들고, 이름은 "희우", 나이는 24로 설정한 뒤 생성된 유저의 정보를 로그로 출력하는 코드를 구현하시오.
val user = User("", 0).____ {
name = "희우"
age = 24
}.____ {
println("새로 생성된 유저: $it")
}
[조건]
- 첫 번째 빈칸에는 객체의 속성을 설정할 수 있는 스코프 함수를,
- 두 번째 빈칸에는 디버깅용 로그를 출력하는 데 적합한 스코프 함수를 넣으세요.
답:
val user = User("", 0).with {
name = "희우"
age = 24
}.also {
println("새로 생성된 유저: $it")
}
보충:
- with는 객체를 인자로 받는 일반함수로 점으로 직접 이어서 사용 불가능
- apply는 객체 자체(this)를 리시버로 받아서 값을 설정하고 그 객체를 반환하므로 점으로 이어서 사용 가능
- also는 객체 자체(it)를 인자로 받아 부가작업하기 적합
val user = User("", 0).apply {
name = "희우"
age = 24
}.also {
println("새로 생성된 유저: $it")
}
4. let, apply, also, run, with 중 하나를 적절히 골라서 문제를 구현하시오.
val userInput: String? = readLine()
// userInput이 null 아니고, 길이가 5 이상이면 대문자로 변환 후
// "입력: (변환된 문자열)" 형태로 출력, 아니면 "입력이 짧거나 없습니다." 출력하는 코드를 작성해봐.
[요구사항]
- userInput이 null이 아니고 공백이 아니면 uppercase()로 대문자로 바꿔서 출력
- 스코프 함수를 꼭 사용해서 작성
[힌트]
- null 체크 → ?.let 또는 takeIf
- 출력은 println
답:
userInput
?.takeIf{ it.isNotEmpty() && it.length >= 5 }
?.run{
println("입력: ${this.uppercase()}")
} ?: println("입력이 짧거나 없습니다.")
5. 아래 조건에 맞추어 내용을 작성하시오
[조건]
- User 객체를 생성할 때, name은 빈 문자열, age는 0으로 초기화
- apply, also, let, run, with 중 적절한 스코프 함수를 골라서 구현
- 스코프 함수를 활용해 아래 작업을 연쇄적으로 수행
- name을 "희우"로 변경
- age를 24로 변경
- "User 정보: 이름=희우, 나이=24" 를 출력
답:
data class User(var name: String, var age: Int)
val user = User("", 0)
user
.apply{
name = "희우"
age = 24}
.also{
println("User 정보: 이름=${it.name}, 나이=${it.age}")
}
6. 아래 코드를 let을 사용해서 구현하시오.
fun printName(name: String?) {
if (name != null) {
println("이름은 ${name}입니다")
}
}
답:
fun printName(name: String?){
name?.let{
println("이름은 $it입니다.")
}
}
7. 아래 코드를 run을 활용해서 객체 생성과 초기화, 동작 수행을 한 번에 수행하게 구현하시오.
data class User(var name: String, var age: Int)
fun createUser(): User {
val user = User("홍길동", 20)
user.age += 1
return user
}
답:
data class User(var name: String, var age: Int)
fun createUser(): User{
val user = User("홍길동", 20)
.apply{
age += 1
}
return user
}
보충:
1. 표현식 함수로 작성하기
fun createUser(): User = User("홍길동", 20).apply { age += 1}
2. run을 사용하기
fun createUser(): User {
return User("홍길동", 20).run {
age += 1
this // run 블록에서 변경한 객체 자신을 반환
}
}
'개발새발 > 코틀린' 카테고리의 다른 글
[코틀린/Kotlin] 코루틴(Coroutine) (3) | 2025.08.28 |
---|---|
[코틀린/Kotlin] sealed class/when (0) | 2025.08.22 |
[코틀린/Kotlin] null처리와 스마트캐스트 (0) | 2025.08.20 |
[코틀린/Kotlin] 확장함수 (0) | 2025.08.19 |
[코틀린/Kotlin] 람다와 고차함수 (3) | 2025.08.18 |