0

New to Kotlin coming from C#.

I am trying create a class that takes in an interchangeable class object through generics. In the class I would like to access attribute values and call methods in the class. I assume this has to be through some kind of reflection mechanism. Digging through Kotlin references I have been trying to apply suggestions to my code, however I get some cryptic errors.

Any help is appreciated.

Error:(35, 20) Kotlin: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 
@InlineOnly public operator inline fun <T> Lazy<T1?>.getValue(thisRef: Any?, property: KProperty<*>): T1? defined in kotlin
@InlineOnly public operator inline fun <V, V1 : T1?> Map<in String, T1?>.getValue(thisRef: Any?, property: KProperty<*>): T1? defined in kotlin.collections
@SinceKotlin public fun <K, V> Map<Class<T1>, T1?>.getValue(key: Class<T1>): T1? defined in kotlin.collections
@JvmName @InlineOnly public operator inline fun <V> MutableMap<in String, in T1?>.getValue(thisRef: Any?, property: KProperty<*>): T1? defined in kotlin.collections
Error:(75, 20) Kotlin: Expression in a class literal has a nullable type 'T1?', use !! to make the type non-nullable
Error:(75, 35) Kotlin: Type parameter bound for T in val <T : Any> KClass<T>.memberProperties: Collection<KProperty1<T, *>>
 is not satisfied: inferred type CapturedTypeConstructor(out T1?) is not a subtype of Any

open class Base<T1, T2> (@Autowired var t2: T2) {

    @Autowired var request: T1? = null

  inline fun <reified T1: Any> retrieveClass(): T1? {
    return request.getValue(T1::class.java)
  }

  fun endpoint(
    @ApiParam(value = "Options", required = true) @Valid @RequestBody
        body: T1
    ): ResponseEntity<MyResponse> {
        type1 = body
        val obj = retrieveClass()
        for (prop in obj::class.memberProperties) {
           println("${prop.name} = ${prop.get(obj)}")
        }
        val usefulResult = obj.usefulMethod()
    }
}

After modifications to access the generic class properties, the code looks like this, with an error in the println:

Error:(82, 56) Kotlin: Out-projected type 'KProperty1<out T1, Any?>' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'


open class Base<T1 : Any, T2 : Any> (@Autowired var t2: T2) {

    @Autowired var request: T1? = null

  fun endpoint(
    @ApiParam(value = "Options", required = true) @Valid @RequestBody
        body: T1
    ): ResponseEntity<MyResponse> {
        val myClass  = body.let { it::class }
        val my2ndClass  = t2.let { it::class }

        for (prop in myClass.memberProperties) {
           println("${prop.name} = ${prop.get(myClass)}")
        }
        val usefulResult = my2ndClass.usefulMethod(myClass)
    }
}
aggaton
  • 3,066
  • 2
  • 25
  • 36
  • Which line in this snippet is line 35/75? Can you mark them with comments? – Salem Nov 22 '17 at 16:32
  • @1blustone Line 35 is the getValue line inside the retrieveClass function. Line 75 is the memberProperties line (for loop) – aggaton Nov 22 '17 at 17:09
  • Possible duplicate of [In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them](https://stackoverflow.com/questions/34498562/in-kotlin-what-is-the-idiomatic-way-to-deal-with-nullable-values-referencing-o) – Salem Nov 22 '17 at 17:17
  • 1
    Both of your errors are caused by this, the second is because `::class` is only valid on non-nullable types. [I opened a discussion about the second a while ago and received some possible workarounds](https://discuss.kotlinlang.org/t/null-safe-class/). – Salem Nov 22 '17 at 17:20
  • @1blustone Alright, looks like I can access the class like this val myClass = body.let { it::class } after I cast T1 to Any in the Base class definition. And I can loop through the properties like this for (prop in myClass.memberProperties) {}. How do I access the actual property values in body. I tried this prop.get(body) as String, but get this cryptic error: Error:(82, 56) Kotlin: Out-projected type 'KProperty1' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1' – aggaton Nov 27 '17 at 16:14

0 Answers0