Hanbit the Developer

Kotlin Documentation | Reflection 본문

Kotlin

Kotlin Documentation | Reflection

hanbikan 2023. 5. 22. 17:13

Kotlin Documentation 시리즈에 대해

Category: Concepts

문서 링크: https://kotlinlang.org/docs/reflection.html


리플랙션은 런타임에서 프로그램의 구조를 살펴볼 수 있는 기능을 제공한다. functional or reactive style을 사용할 때, Kotlin의 일급 객체(first-class citizens, 변수나 데이터에 저장될 수 있고 함수 인자로 넘길 수 있으며 함수의 결과로서 반환될 수 있는 특징이 있다.)인 함수와 프로퍼티를 관찰해야 할 필요성이 있다.

JVM dependency

리플랙션을 사용하기 위해 의존성을 추가해야 한다.

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.21")
}

Class references

val c = MyClass::class

해당 래퍼런스는 KClass이다.(https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-class/)

Bound class references

val widget: Widget = ...
assert(widget is GoodWidget) { "Bad widget: ${widget::class.qualifiedName}" }

Callable references

함수, 프로퍼티, 생성자로의 참조는 function type의 인스턴스로 사용될 수 있다.

callable references의 공통 슈퍼타입은 KCallable<out R>이며 여기서 R은 반환값이다. 특히 프로퍼티의 경우 프로퍼티의 타입, 생성자의 경우 생성하는 객체의 타입이다.

Function references

fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd))

오버로드 함수의 경우 타입 추론을 통해 자동으로 연결된다.

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)

또는 아래와 같이 명시할 수도 있다.

val predicate: (String) -> Boolean = ::isOdd   // refers to isOdd(x: String)

Property references

아래 코드에서 ::x는 KProperty<Int>에 해당한다.

var x = 1

fun main() {
    println(::x.get())
    println(::x.name)
		::x.set(2)
}

var y = 1과 같이 변경 가능한 프로퍼티의 경우에는 KMutableProperty<Int> 타입이다.

Interoperability with Java reflection

자바 리플랙션 객체와의 매핑을 제공한다. 예를 들어 backing field, getter를 얻고 싶다면 아래와 같이 코드를 작성할 수 있다.

import kotlin.reflect.jvm.*

class A(val p: Int)

fun main() {
    println(A::p.javaGetter) // prints "public final int A.getP()"
    println(A::p.javaField)  // prints "private final int A.p"
}

자바 클래스에 대응하는 코틀린 클래스를 얻고 싶다면 .kotlin 확장 프로퍼티를 사용하면 된다.

fun getKClass(o: Any): KClass<Any> = o.javaClass.kotlin

Constructor references

class Foo

fun function(factory: () -> Foo) {
    val x: Foo = factory()
}
function(::Foo)