Prologue

코틀린에서 사용하는 더블콜론 참조에 대해서 알아보려고 한다.

리플렉션(Reflection)이란

코틀린에서 더블콜론(::)은 리플렉션을 위해 사용한다. 리플렉션이란 코드를 작성하는 시점에는 런타임상 컴파일된 바이트 코드에서 내가 작성한 코드가 어디에 위치하는지 알 수 없기 때문에 바이트 코드를 이용해 내가 참조하려는 값을 찾기위해 사용한다.

자바와 코틀린에서의 리플렉션

1
2
SomeClass.class -> 클래스 그 자체를 리플렉션
someInstance.getClass() -> 인스턴스에서 클래스를 리플렉션
  • 자바에서는 클래스를 참조할 때 위와 같이 사용한다.
1
2
SomeClass::class
someInstance::class
  • 코틀린에서는 더블콜론을 리플렉션을 위해 사용하며 위와 같은 형태로 사용한다.

하지만 우리가 액티비티를 넘길 때는 SomeClass::class.java와 같이 끝에 .java가 붙는 것을 볼 수 있다. 그 이유는 자바에서 쓰는 클래스와 코틀린에서 쓰는 클래스가 다르기 때문이다.

자바에서의 SomeClass.class는 Class를 리턴한다. 반면, 코틀린에서는 SomeClass::class를 하면 KClass를 리턴한다. 그렇기 때문에 KClass를 Class로 바꾸어 주어야하는데 이때 .Java를 이용하여 자바 클래스 값을 받는다.

KClass 안의 java의 getter는 위 그림과 같이 확장함수 형태로 되어있으며 KClass에서 자바의 클래스 타입을 반환한다.

코틀린에서의 함수참조

코틀린에서 SomeClass::class와 같이 클래스를 참조할 수도 있지만 SomeClass:Method와 같이 클래스 내의 메소드도 참조할 수 있고 ::Function 형식의 함수도 참조할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fun main(args: Array<String>) {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8)

numbers.filter(::isOdd)
.forEach {
println(it)
}

}

fun isOdd(x: Int): Boolean {
return x % 2 != 0
}

// 단축형
//fun isOdd(x: Int) = x % 2 !=0
  • isOdd() 함수를 filter를 사용한 코드이다. filter를 사용하면서 함수참조를 이용해 ::isOdd 형태로 함수를 호출하였다.
  • 필터의 원형은 IntArray에서 Int 값을 받아 Boolean을 반환하는 inline 함수이다. 마찬가지로 Int를 받아 Boolean을 반환하기 때문에 함수를 참조하여 동일한 형식의 isOdd를 사용할 수 있다.

Reference