Post

(Kotlin) 제네릭 - 타입 파라미터 소거(erasure), inline 실체화(reified)

타입 파라미터 소거

[Kotlin] as와 타입 캐스팅. 런타임 에러. 타입 파라미터 소거(erasure)

런타임 타입 검사 : inline + reified (실체화한 타입 파라미터)
1
2
3
inline fun <reified T> isA(value: Any) = value is T
>>> isA<String>("a")
true
  • 이게 가능한 이유는 인라인 함수는 함수 바디 코드가 함수 호출부에 삽입 되기 때문에, 타입 인자가 아니라 구체적인 타입을 사용할 수 있기 때문이다.
  • 자바에서는 reified를 사용하는 inline 함수를 호출할 수 없다.
  • 자바에서는 코틀린 인라인 함수를 다른 보통 함수처럼 호출해버려서 타입 정보가 사라지기 때문이다.
  • inline reified 함수 내에서 위 예제처럼 실제 타입간 비교 등을 작성하는 경우, 자바에서 함수 호출하는 식으로 불러버리면 T타입 정보가 사라져 타입 비교가 예상과 다르게 동작하게 된다. 그래서 아예 호출하지 못하게 만든 듯.
  • inline이기 때문에, 코드 조각을 가능한 작게 유지하는 것이 좋다.

실체화한 타입 파라미터를 사용한 표준 라이브러리로는 filterIsInstance<T>()가 있다.

1
2
3
>>> val li = listOf(1, "b", 3)
>>> li.filterIsInstance<Int>()
[1, 3]
클래스 참조(멤버 참조)와 연계해서 사용
1
2
3
4
5
inline fun <reified T: Activity> Context.startActivity() {
val intent = Intent(this, T::class.java)
startActivity(intent)
}
>>> startActivity<DetailActivity>()    // 가독성 향상
reified 제약

일부는 실체화의 개념으로 인해 생기는 제약이며, 나머지는 코틀린이 실체화를 구현하는 방법에 의해 생기는 제약이므로 이후 해결될 수 있다.

  • T의 인스턴스를 생성할 수 없다.
  • T의 동반 객체 메소드를 호출할 수 없다.
  • 실체화한 타입 파라미터를 요구하는 함수에 실체화하지 않은 타입 파라미터로 받은 타입을 넘길 수 없다.
  • 클래스, 프로퍼티의 타입 파라미터를 reified로 지정할 수 없다.
  • inline과 함께 사용해야 한다. 인라인 함수에만 사용할 수 있기 때문에 실체화한 타입 파라미터를 사용하는 함수는 자신에게 전달되는 모든 람다를 인라이닝한다. 그러나 람다를 인라이닝할 수 없는 상황이거나 성능 문제로 인라이닝하고 싶지 않은 경우 noinline 변경자를 함수 타입 파라미터에 붙여서 인라이닝을 금지할 수 있다.
This post is licensed under CC BY 4.0 by the author.