Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Kotlin gets Reflection

3,418 views

Published on

Presented at JVM Language Summit, 2013

Published in: Technology, Education
  • Be the first to comment

Kotlin gets Reflection

  1. 1. KOTLIN GETS REFLECTION Andrey.Breslav@JetBrains.com
  2. 2. Introspection is examination of one's own conscious thoughts and feelings. Schultz, D. P.; Schultz, S. E. (2012). A history of modern psychology (10th ed.)
  3. 3. LEGAL Takeiteasy
  4. 4. DON’T JUDGE STRICTLY
  5. 5. OUTLINE • Intro • Ways of Introspection • Reflection API • Reflection Literals • Expression Trees • Conclusion
  6. 6. USE CASES Dependency Injection Data binding Convention over configuration Hacks Workarounds Black Magic
  7. 7. INTROSPECTION Instances - what is your class? Classes & Types - what are your members? supertypes? create an instance Methods/Fields - what are your parameters/types/etc? run with these args. Expressions - ???
  8. 8. JAVA.LANG.REFLECT? Top-level functions Default arguments Properties Nullable types Special types (Nothing, (Mutable)List, etc) … + modules (classes in a package)
  9. 9. METADATA *.kt *.class (kotlin) *.jar (kotlin) kotlin symbols kotlin symbols kotlin symbols java symbols kotlinc
  10. 10. HOW TO STORE METADATA? *.class Custom attributes Annotations Annotate each symbol One big annotation
  11. 11. ONE BIG ANNOTATION *.class @KotlinClass(“data”) val/var types defaults … Java definitions erased generic annotations …
  12. 12. RE-USE j.l.Class *.kt *.class AST @KotlinClass Symbols
  13. 13. DISCREPANCY 1 java.lang.annotation.Annotation vs org.jetbrains.kotlin.internal….AnnotationDescriptor
  14. 14. PURE JAVA CLASSES? j.l.Class *.kt *.class AST @KotlinClass Symbols *.java java2k
  15. 15. DISCREPANCY 2 // Java class Foo { @NotNull String getFirstName() { … } String getMiddleName() { … } } // Corresponding Kotlin class Foo { fun getFirstName(): String fun getMiddleName(): String? }
  16. 16. DISCREPANCY 2 j.l.Class *.class Symbols *.java java2k annotations.xml
  17. 17. SUMMARY 1 Kotlin-specific reflection API - works for Java as well Metadata representation - one big annotation - re-use code from the compiler Problems - representing annotations - nullable/mutable types
  18. 18. ENTRY POINTS
  19. 19. SYNTAX (TENTATIVE) Foo::class expr::class List<String>::member org.sample.bar::member expr::member expr::type (maybe)
  20. 20. USE CASES: PASSING CODE AROUND list.filter(Item::isValid) * Why not a lambda? foo {a, b, c -> bar(a, b, c) }
  21. 21. USE CASES: CONSTRUCTORS fun <T: Tag> tag( create: () -> T, init: T.() -> Unit ) { … } tag(::DIV) { // kara.tags::DIV … }
  22. 22. USE CASES: DATA BINDING class Model { var userName: String by observable() } bind(view.textField, model::userName)
  23. 23. GENERICS? fun foo(s: String): Foo ::foo : (String) -> Foo fun <T> foo(t: T): T { … } ::foo : ∀T.(T) -> T
  24. 24. RANK-2 POLYMORPHISM interface Function1<P1, R> { R invoke(P1 p1); } vs interface GenericFunction1_1<P1, R> { <T> R<T> invoke(P1<T> p1); }
  25. 25. ENCODING FOR FUNCTIONS f: (Foo) -> Bar is Function1<Foo, Bar> interface Function1<P1, R> { R invoke(P1 p1); }
  26. 26. GENERIC FUNCTIONS f: <T>(List<T>) -> T • GenericFunction<List<T>, T> ??? • GenericFunction<T, List<T>, T> ??? interface GenericFunction1_1<P1, R> { <T> R<T> invoke(P1<T> p1); } + Kinds
  27. 27. GENERICS class Foo<T> { fun <R> bar(t: T): R { … } } Foo<T’>::bar<R’> : (T’) -> R’
  28. 28. EXPR::TYPE val x: Any = listOf(1, 2, 3) x::class -> java.util.ArrayList x::type -> java.util.ArrayList<Unknown> vs val x = listOf(1, 2, 3) // x: List<Int> x::class -> java.util.ArrayList x::type -> java.util.ArrayList<Int>
  29. 29. DELEGATED PROPERTIES val foos: List<Foo> by Lazy { foos.find(…) } class Lazy<T>(compute: () -> T) { private var value: T? = null fun get(me: Any, p: PropertyMetadata): T { if (value == null) value = compute() return value } }
  30. 30. DELEGATED PROPERTIES val foos: List<Foo> by Lazy { foos.find(…) } ::foos::delegate : Lazy<Foo> ::foos : Property<List<Foo>> or ::foos.delegate : Lazy<Foo> ::foos : DelegatedProperty< List<Foo>, Lazy<Foo> >
  31. 31. SUMMARY 2 Reflection literals - Static name lookup & typing - Generics are hard, as usual
  32. 32. CODE INTROSPECTION I told you!
  33. 33. USE CASES: LINQ db .selectFrom(::User) .where { lastName.startsWith(“A”) } .orderBy { lastName + firstName }
  34. 34. server client server USE CASES: WEB html { body { onLoad { ... } ... } }
  35. 35. EXPRESSION TREES fun onLoad(ast: Expression<() -> Unit>) { ... } onLoad { ... // compiled to factory calls } At run time the tree can be translated to JS
  36. 36. SUMMARY Kotlin’s introspection facilities - Reflection API - Java interop is the hardest issue - Reflection literals - Issues with generics - Expression trees - Compiler as a service

×