mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-05-12 15:53:40 +00:00
Both for callables obtained via reflection API (KClass.members etc) and for callables obtained via ::-references, the instance parameter is now the class which was used to construct the type at the left-hand side of the reference, NOT the class where the callable is originally declared as is known at compile-time. The reason is to reduce the difference in behavior of KCallable.call vs FunctionN.invoke: the latter always required the subclass instance for a fake override, and it's reasonable that the former would require it as well. Note that in Java reflection, behavior could differ in a similar case. For a simple fake override, Class.getMethod would return the method declared in the base class and that method will accept instances of the base class in invoke. However, it's difficult to rely on this behavior because if there's a bridge for a fake override in the derived class (e.g. when overridden members have different signatures), the returned Method object is accepting the derived class as the receiver. This just confirms the fact that Java reflection operates on a different level of abstraction, namely JVM methods in .class files, which is not applicable to our use cases directly. Another reason not to replicate Java reflection's behavior is the uncertainty as to which member is returned in case there are several in the hierarchy for a given fake override: see the "otherwise one of the methods is chosen arbitrarily" note in javadoc on Class.getMethod. #KT-24170 Fixed
32 lines
1.1 KiB
Kotlin
Vendored
32 lines
1.1 KiB
Kotlin
Vendored
// IGNORE_BACKEND: JS, NATIVE, JS_IR, JVM_IR
|
|
// WITH_REFLECT
|
|
|
|
import kotlin.reflect.full.instanceParameter
|
|
import kotlin.reflect.jvm.jvmErasure
|
|
import kotlin.reflect.jvm.javaType
|
|
import kotlin.test.assertEquals
|
|
|
|
open class A {
|
|
val property = "OK"
|
|
|
|
fun function() {}
|
|
}
|
|
|
|
class B : A()
|
|
|
|
fun box(): String {
|
|
assertEquals(B::class, B::property.instanceParameter!!.type.jvmErasure)
|
|
assertEquals(B::class.java, B::property.instanceParameter!!.type.javaType)
|
|
assertEquals(B::class, B::function.instanceParameter!!.type.jvmErasure)
|
|
assertEquals(B::class.java, B::function.instanceParameter!!.type.javaType)
|
|
|
|
val property = B::class.members.single { it.name == "property" }
|
|
val function = B::class.members.single { it.name == "function" }
|
|
assertEquals(B::class, property.instanceParameter!!.type.jvmErasure)
|
|
assertEquals(B::class.java, property.instanceParameter!!.type.javaType)
|
|
assertEquals(B::class, function.instanceParameter!!.type.jvmErasure)
|
|
assertEquals(B::class.java, function.instanceParameter!!.type.javaType)
|
|
|
|
return "OK"
|
|
}
|