Last active
July 30, 2020 14:13
-
-
Save begomez/5858179c6e8eafd214606efd05e1fd79 to your computer and use it in GitHub Desktop.
Reflection in Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.bgomez.recipapp | |
import kotlin.reflect.* | |
import kotlin.reflect.full.findAnnotation | |
import kotlin.reflect.full.memberProperties | |
/** | |
* Custom annotation that can be applied on class props | |
*/ | |
@Target(AnnotationTarget.PROPERTY) | |
annotation class MyCustomAnnotation(val value : String) | |
/** | |
* Data class for Person. | |
* Applies annotations on some properties | |
* | |
* Created by bernatgomez on July,2020 | |
*/ | |
data class Person( | |
@MyCustomAnnotation(value="Some annotation value goes here...") val personName : String, | |
val personAge : Int) { | |
fun displayAgeInformation(threshold : Int) : Unit { | |
println("Is $personName an adult? ${isAdult(threshold)}") | |
} | |
fun isAdult(threshold: Int) : Boolean = this.personAge >= threshold | |
fun paramsExample(num : Int, str : String, p : Person) : Unit {} | |
} | |
/** | |
* Execution entry point | |
*/ | |
fun main(args : Array<String>) { | |
accessClass() | |
accessConstructors() | |
accessCallable() | |
accessFunction() | |
accessFunctionParameters() | |
accessProperty() | |
accessAnnotations() | |
} | |
fun accessClass() { | |
val p = Person("John", 20) | |
//XXX: Kotlin reflection | |
val pClazz0 : KClass<Person> = Person::class | |
val pClazz1 : KClass<Person> = p.javaClass.kotlin | |
//XXX: Java reflection | |
val pClazz2 : Class<Person> = Person::class.java | |
println("Person class props-------------------------------------------------------------------") | |
println(pClazz0.qualifiedName) | |
println(pClazz1.qualifiedName) | |
println(pClazz2.name) | |
//XXX: switch from one API to another | |
println(pClazz2.kotlin.qualifiedName) | |
} | |
fun accessConstructors() { | |
val clazz : KClass<Person> = Person::class | |
val construcs : Collection<KFunction<Person>> = clazz.constructors | |
println("Person constructors------------------------------------------------------------------") | |
construcs.forEach {construc -> | |
println("Constructor $construc") | |
} | |
} | |
fun accessCallable() { | |
val p = Person("John", 20) | |
//XXX: member ref to fun, function will be called, params needed | |
val mCall : KCallable<Unit> = p::displayAgeInformation | |
//XXX: ok, params match | |
mCall.call(THRESHOLD) | |
//FIXME: ko, no match | |
//mCall.call("21") | |
//FIXME: ko, params required | |
//mCall.call() | |
//XXX: member ref to prop, accessor will be called, NO Params needed | |
var pCall : KCallable<Int> = p::personAge | |
println("${p.personName}'s age is ${pCall.call()}") | |
//XXX: member ref directly through class | |
pCall = Person::personAge | |
println("${p.personName}'s age is ${pCall.call(p)}") | |
} | |
fun accessFunction() { | |
val p = Person("John", 20) | |
println("Function info------------------------------------------------------------------------") | |
val mFun : KFunction<Boolean> = p::isAdult | |
println("infix ? ${mFun.isInfix}") | |
println("inline ? ${mFun.isInline}") | |
println("suspend? ${mFun.isSuspend}") | |
println("open ? ${mFun.isOpen}") | |
val result = mFun.call(THRESHOLD) | |
println("Result is $result of type ${result.javaClass}") | |
} | |
fun accessFunctionParameters() { | |
val p = Person("John", 20) | |
val mFun : KFunction<Unit> = p::paramsExample | |
val mParams : List<KParameter> = mFun.parameters | |
mParams.forEach { param -> | |
println("Param ${param.name} of type ${param.type.toString()}") | |
} | |
} | |
fun accessProperty() { | |
val mGlobalProp : KMutableProperty0<Int> = ::THRESHOLD | |
println("global var has value ${mGlobalProp.get()}") | |
mGlobalProp.set(21) | |
println("global var has value ${mGlobalProp.get()}") | |
val p1 = Person("John", 40) | |
val p2 = Person("Jane", 50) | |
val mProp : KProperty1<Person, Int> = Person::personAge | |
println("${p1.personName}'s age is ${mProp.get(p1)}") | |
println("${p2.personName}'s age is ${mProp.get(p2)}") | |
val mProps : Collection<KProperty1<Person, *>> = p1.javaClass.kotlin.memberProperties | |
println("Class props--------------------------------------------------------------------------") | |
mProps.forEach { prop -> | |
println(prop.name) | |
} | |
} | |
fun accessAnnotations() { | |
val p = Person("Joe", 60) | |
val mProps : Collection<KProperty1<Person, *>> = p.javaClass.kotlin.memberProperties | |
println("Annotations--------------------------------------------------------------------------") | |
for (mProp in mProps) { | |
val mCustomAnnotation : MyCustomAnnotation? = mProp.findAnnotation<MyCustomAnnotation>() | |
mCustomAnnotation?.let { | |
println(it.annotationClass ) | |
println(it.value) | |
} | |
} | |
} | |
var THRESHOLD = 18 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment