때떄로 암시적으로 사용할 수 있는 경우에도, this를 사용해서 명시적으로 코드를 작성하는 경우가 있다.

클래스의 메서드임을 나타내기 위한 this


class User : Person() {
    private var beersDrunk: Int = 0
    fun drinkBeers(num: Int) {
        this.beersDrunk += num
    }
}

확장 리시버를 명시적으로 참조

fun <T : Comparable<T>> List<T>.quickSort1(): List<T> {
    if (size < 2) return this
    val pivot = first()
    val (smaller, bigger) = drop(1).partition { it < pivot }
    return smaller.quickSort1() + pivot + bigger.quickSort1()
}

fun <T : Comparable<T>> List<T>.quickSort2(): List<T> {
    if (size < 2) return this
    val pivot = this.first()
    val (smaller, bigger) = this.drop(1).partition { it < pivot }
    return smaller.quickSort2() + pivot + bigger.quickSort2()
}

위의 경우에서는 명시적 사용의 실질적 차이는 존재 하지 않는다.

여러개의 리시버

class Node(val name: String) {
    fun makeChild(childName: String) = create("$name. $childName").apply { print("Created ${name}") }

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

fun main() {
    val node = Node("parent")
    node.makeChild("child")
}

스코프 내부에 둘 이상의 리시버가 있는 경우 명시적으로 나타내면 좋다. 특히나 , 스코프 함수들중 this를 사용하는 run,with,apply의 경우 this의 생략이 가능하다.

하지만 이경우 this 생략시 문제가 생길 수 있다

위의 code는

Created parent. child

의 결과를 예상해볼 수 있지만.

실제로는

Created parent

라는 결과가 나오게 된다.

왜냐하면 create의 결과 자체가 Node?라서 null가능성이 있기 때문에 이 경우에는 null가능성을 언팩해야한다. 즉,