kotlin - What is the purpose of having bound class reference return a covariant type? -


i'm playing reflection , came out problem. when using bound class reference via ::class syntax, covariant kclass type:

fun <t> foo(entry: t) {     with(entry::class) {        // instance of kclass<out t>     } } 

as learn docs, return exact type of object, in case instance of subtype of t, hence variance modifier. prevents retrieving properties declared in t class , getting value (which i'm trying do)

fun <t> foo(entry: t) {     with(entry::class) {        (prop in memberproperties) {            val v = prop.get(entry) //compile error: can't consume t        }     } } 

i found solution using javaclass.kotlin extension function on object reference, instead invariant type:

fun <t> foo(entry: t) {     with(entry.javaclass.kotlin) {        // instance of kclass<t>     } } 

this way, both exact type @ runtime , possibility consume type.

interestingly, if use supertype instead of generic, latter method still access correct type, without need of variance:

class derived: base()  fun foo(entry: base) {     with(entry.javaclass.kotlin) {        println(this == derived::class)     } }  fun main(args: array<string>) {     val derived = derived()     foo(derived) // prints 'true' } 

if got correct, ::class equal calling java getclass, returns variant type wildcard, while javaclass getclass cast specific type. still, don't why ever need covariant kclass, when limits me produce type, given there other ways access exact class @ runtime , use freely, , wonder if more immediate ::class should return invariant type design.

the reason covariance in bound ::class references is, actual runtime type of object expression evaluated might differ declared or inferred type of expression.

example:

open class base class derived : base()  fun somebase(): base = derived()  val kclass = somebase()::class 

the expression somebase() typed base, @ runtime it's derived object gets evaluated to.

typing somebase()::class invariant kclass<base> incorrect, in fact, actuall result of evaluating expression kclass<derived>.

to solve possible inconsistency (that lead broken type-safety), bound class references covariant: somebase()::class kclass<out base>, meaning @ runtime somebase() might subtype of base, , therefore might class token of subtype of base.

this is, of course, not case unbound class references: when take base::class, know sure it's class token of base , not of of subtypes, it's invariant kclass<base>.


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -