본문 바로가기
공부/이펙티브코틀린

아이템 15 - 리시버를 명시적으로 참조하라

by 띵커베르 2024. 4. 7.
728x90
  • 리시버?
    • 확장 함수나 확장 속성, 또는 수신 객체 람다에서 대상이 되는 객체를 의미한다
    • 확장 함수나 속성을 호출할 때,  그 앞에 오는 객체가 바로 리시버 객체이다.
    • 수신 객체 지정 람다에서는 람다 내부에서 사용 가능한 컨텍스트 객체를 가리킨다.
      • 확장 함수: 특정 타입의 객체에 대해 호출되며, 그 타입의 객체가 리시버
      • 수신 객체 지정 람다: applu, run, with, also, let 같은 함수는 모두 리시버 객체를 가지며, 람다 내부에서 직접 호출할 수 있다.
fun User.printInfo() {
    println("Name: $name, Age: $age") // 확장 함수 내에서 'this' 생략 가능
}

val user = User("injin Jeong", 10).apply {
    name = "injin Jeong" // 'apply' 내에서 'this'를 생략하고 리시버의 속성에 접근
    birthday() // 'this' 생략하고 리시버의 함수 호출
}

 

class Node(val name: String) {
    fun makeChild(childName: String) =
        create("$name.$childName")
//            .apply { println("Created $name") } // Created parent
//            .apply { println("Created ${this?.name}") } // Created parent.child (좋은방법은 아님)
//            .also { println("Created ${it?.name}") } // Created parent.child
//            .let { println("Created ${it?.name}") } // Created parent.child

    private fun create(name: String): Node? = Node(name)
}

 

참고: apply, with, let, also, run 에 궁금하다면

https://jeong0427.tistory.com/212

 


 

정리

  • 짧게 적을 수 있다는 이유만으로 리시버를 제거하지 말기 바랍니다.
  • 여러 개의 리시버가 있는 상황 등에는 리시버를 명시적으로 적어 주는 것이 좋습니다.

 

생각

  • js 할때는 리시버를 무조건 적어준거 같은데 코틀린에서는 의외로 잘 안적었던거 같은데, 앞으로는 주로 적어서 명시적으로 표현해 줘야겠다고 생각 함.
  • 안적었던 이유는 scope 함수 안에서 주로 사용하고 문법을 아니깐..이라고 생각했던..별 의미는 없었음
  • 아래코드는 억지 코드이긴 하지만 여러 개의 리시버가 있는 상황 코드..이렇게 할 일이 있을까 싶지만 코드를 적은김에 추가 함
class OuterTest {
    val outerProperty = "Outer property"

    fun outerFunction() {
        println("This is from the outer function.")
    }

    inner class Inner {
        val innerProperty = "Inner property"

        fun nestedFunction() {
            // 여기서 this는 Inner 객체를 가리킵니다.
            println(this.innerProperty) // "Inner property" 출력

            this@OuterTest.outerFunction() // OuterTest의 함수 호출
            println(this@OuterTest.outerProperty) // OuterTest의 프로퍼티 접근
        }

        fun outerFunction() {
            println("This is from the outer function.")
        }

        fun test() {
            // 직접적으로 outerFunction 호출 시, Inner의 outerFunction이 호출됩니다.
            println(outerFunction())
            // OuterTest의 함수를 호출하려면, 리시버를 명시적으로 지정해야 합니다.
            println(this@OuterTest.outerFunction())
        }
    }

    fun doSomethingWithInner() {
        Inner().nestedFunction() // Inner의 확장 함수 호출
        Inner().test()
    }
}
728x90

댓글