본문 바로가기

[Kotlin] Scope Function 본문

Kotlin

[Kotlin] Scope Function

00rigin 2024. 12. 3. 00:35

Kotlin은 표준 스코프 함수를 제공한다.

특정 객체의 컨텍스트 내에서 정해진 동작을 수행하기 위해 기본적으로 제공되는 함수이다.

일반적으로 람다 함수로서 많이 사용하게 되는데, 람다가 적용되는 객체에 임시로 스코프를 형성하여 바로 핸들링하는 편리함을 제공한다.

 

가끔 사용하다가 헷갈릴 때 가 있어서 한번 정리를 해두려고 한다.

 

종류 : apply, run, with, alse, let

 

apply

적용되는 객체를 참고하여 새로운 인스턴스를 만들 수 있다. 이때, 초기화 작업과 특정 동작을 수행하여 인스턴스를 생성하고 반환한다.

fun main(args: Array<String>) {
    val youngJuni = Human("juni", 19)
    val oldJuni = youngJuni.apply {
        name = "oldJuni"
        addOneYear()
    }
    print("youngJuni : ${youngJuni.name} \n")
    print("youngJuni age : ${youngJuni.age} \n")
    print("oldJuni : ${oldJuni.name} \n")
    print("oldJuni age : ${oldJuni.age} \n")
}

class Human(var name: String, var age: Int) {
    fun addOneYear() {
        age++
    }
}

run

apply와 비슷하지만, 인스턴스를 반환하는 것이 아닌, 스코프 내 실행 값을 반환한다.

fun main(args: Array<String>) {
    val youngJuni = Human("juni", 19)
    val oldJuniAge = youngJuni.run { age+1 }

    println("oldJuniAge: $oldJuniAge")
}

class Human(var name: String, var age: Int) {
    fun addOneYear() {
        age++
    }
}

다만, run 내부에서 메서드를 부르게 된다면, 아래처럼 동작한다.

val oldJuniAge = youngJuni.run { addOneYear(); }

run 함수는 마지막 식의 값을 반환 하기 때문에 void 메서드인 addOneYear의 반환 값인 Unit을 반환한다.

원하는 동작을 하려면 아래처럼 결과 '값' 을 반환해야 한다.

val oldJuniAge = youngJuni.run { 
        addOneYear(); 
        age
    }

 

with

run과 거의 비슷한 동작을 수행한다.

run은 객체에서 바로 호출을 하고, object.run{}

with은 파라미터로 객체를 전달해야 한다. with(object) {}

이렇게 사용법만 보면 무슨 차이가 있지?? 싶지만, 사용법 때문에 null safe한 동작 여부가 갈린다.

val firstOldJuni = youngJuni?.run {age + 1}
val secondOldJuni = with(youngJuni) {age + 1}

나라면, 왠만하면 run을 사용할 것 같다.

 

also / let

also 는 apply와 대치된다.

let 은 run과 대치된다.

차이점은 also,let은 it 을 사용할 수 있다는 것이다.

it을 사용하면, 명시적으로 객체를 명확하게 지정할 수 있다.

val youngJuniAge = youngJuni.let { it.age }
fun main(args: Array<String>) {
    val youngJuni = Human("Juni", 1)
    val oldJuni = youngJuni.also {
        it.name = "Old Juni"
        it.age = 10
    }
    val juniList = listOf(youngJuni, oldJuni)
    juniList.forEach { println("${it.name} is ${it.age} year(s) old") }
}

class Human(var name: String, var age: Int) {
    fun addOneYear() {
        age++
    }
}

 

Comments