Kotlin을 사용하다 보면 종종 더블 콜론(::)을 사용하는 사례를 볼 수 있다.
이는 과연 무엇일까?
더블 콜론은 리플렉션(Reflection)을 위해 사용합니다.
Reflection이란?
Reflection is a set of language and library features that allows you to introspect the structure of your program at runtime.
공식 문서에서는 이런 식으로 소개하고 있습니다.
"리플렉션은 런타임 시 프로그램 구조를 검사할 수 있는 언어 및 라이브러리 기능 집합이다."라고 표현하고 있습니다.
코드를 작성하는 시점에 런타임 시점의 컴파일된 바이트 코드 중 원하는 함수의 위치를 알 수 없기 때문에
런타임 시의 바이트 컴파일 된 바이트 코드를 이용하여 해당 함수의 값을 찾기 위해 사용합니다.
리플렉션은 런타임에 프로그램의 클래스를 조사하기 위해 사용되는 기술입니다.
코드를 작성하는 시점이 아닌 프로그램이 실행 중 일 때 인스턴스 등을 통해 객체의 내부 구조를 파악할 수 있습니다.
코틀린에서 더블콜론(::)을 명시하면, 변수나 클래스에 대한 참조를 할 수 있습니다.
더블콜론을 명시하면 변수가 아닌 객체로 접근할 수 있기 때문입니다.
리플렉션이 무슨 일을 하는지 조금 더 쉽게 알아보겠습니다.
클래스 참조
가장 기본적인 리플렉션의 기능은 Kotlin 클래스에 대한 런타임 참조를 가져오는 것입니다.
val c = MyClass.class
여기서 참조는 KClass 유형입니다.
함수 참조
리플렉션을 이용하면 함수를 참조할 수 있습니다.
fun isOdd(x: Int) = x % 2 != 0
해당 함수는 Int 형태의 x를 받아 그 수가 홀수인지 아닌지에 따라 참, 거짓을 반환합니다.
위와 같이 정의된 함수를 선언한 경우 직접 호출할 수 있습니다.
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd))
inline fun IntArray.filter(
predicate: (Int) -> Boolean
): List<Int>
해당 함수에 사용되는 filter의 내부 모습입니다.
predicate라는 (Int)를 입력받아, Boolean을 반환하기 때문에 함소를 참조하여 동일한 형식인 isOdd를 사용할 수 있습니다.
이러한 기능은
더블 콜론의 예상 유형이 콘텍스트에서 알려진 경우
오버로드된 함수와 함께도 사용할 수 있습니다.
이처럼 함수가 오버로드 되더라도
Int일 경우엔 Int로
fun isOdd(x: Int) = x % 2 != 0
fun isOdd(s: String) = s == "brillig" || s == "slithy" || s == "tove"
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd)) // refers to isOdd(x: Int)
String일 경우엔 각각에 맞는 타입으로
fun isOdd(x: Int) = x % 2 != 0
fun isOdd(s: String) = s == "brillig" || s == "slithy" || s == "tove"
val strings = listOf("brillig", "asdf", "asdfa")
println(strings.filter(::isOdd)) // refers to isOdd(x: String)
값을 제대로 출력하는 모습을 볼 수 있다.
속성 참조
또한 속성을 참조할 수도 있습니다.
val x = 1
fun main() {
println(::x.get())
println(::x.name)
}
x의 속성을 참조하여,
get()을 사용해 안에 들어 있는 값과,
name을 사용하여 해당 변수의 이름을 알 수 있었습니다.
var y = 1
fun main() {
::y.set(2)
println(y)
}
처음에는 1로 선언된 값이 참조와 set 함수를 이용하여
변수를 var로 선언한다면 getter와 setter가 모두 생기기 때문에 값을 변경해 주는 것도 가능합니다.
val strs = listOf("a", "bc", "def")
println(strs.map(String::length))
map을 이용하여 String을 참조하면, 이런 식으로 문자열의 길이도 구할 수 있습니다.
'Kotlin' 카테고리의 다른 글
Kotlin - Infix 함수 (2) | 2023.02.20 |
---|---|
::class.java는 무엇일까 (0) | 2023.02.07 |
[Kotlin] - map함수 (리스트 값 변경하기) (0) | 2023.02.02 |
[Kotlin] - filter사용하기 (0) | 2023.01.30 |
[Kotlin] lateinit, by lazy (0) | 2023.01.27 |