https://kotlinlang.org logo
Title
c

ClaudiuB

01/17/2018, 8:37 PM
In my experience,
as?
or
as
doesn't seem to work when using them with generic
T: KClass<out Any>
. For example
someClass as T
will return
someClass
, even when
T
is not `someClass`'s ancestor. if anyone could put an eye on the code in the comment to this, that would be great! Currently, in trying to achieve
instanceof
-like behavior, my method returns
true
for
Nothing::class instanceof Number::class
and I wish I was joking 🤖 . I've been trying to figure this out for maybe 3 hours now?If I'm using generics properly, then
as
and
as?
are broken when used with generics?
infix fun <PossibleSuperClass> KClass<out Any>.instanceof(clazz: PossibleSuperClass)
        : Boolean where PossibleSuperClass : KClass<out Any> {
    return try {
        this as PossibleSuperClass
        true
    } catch (e: ClassCastException) {
        false
    }
}
Same happens if i go the
as?
way. My hunch is there's issues with
PossibleSuperClass
. When debugging, `this`/`$receiver` is
java.lang.Void
,
clazz
is
kotlin.Number
, and
this as PossibleSuperClass
returns `this`s value,
java.lang.void
in this case (???). The value of
this
is returned every time even when an exception should be thrown or
null
should be returned
c

cedric

01/17/2018, 8:40 PM
Probably a simple consequence of erased generics
c

ClaudiuB

01/17/2018, 8:40 PM
Can I unerase it/them?
c

cedric

01/17/2018, 8:40 PM
Somewhat, with
reified
. But the code you pasted above is scary
k

kevinmost

01/17/2018, 8:40 PM
what are you trying to check there?
Nothing::class is Number::class
wouldn't even work
you could do
Nothing::class is Number
which will return false, because you're checking if a
KClass
object is an instance of
Number
, which it isn't
c

ClaudiuB

01/17/2018, 8:41 PM
I'm just trying to check if a class a is a subclass of b
reverse behavior of java class isAssignableFrom
k

kevinmost

01/17/2018, 8:42 PM
you can't do that with
is
or
instanceof
. In Java that's something like
Foo.class.isAssignableTo(Bar.class)
I believe
c

cedric

01/17/2018, 8:42 PM
Are you working with classes or values? If the former,
isAssignableFrom
is probably what you want
k

kevinmost

01/17/2018, 8:42 PM
assignableFrom, yeah
c

ClaudiuB

01/17/2018, 8:42 PM
I wanted a java-agnostic way of doing this 😞
k

kevinmost

01/17/2018, 8:42 PM
KClass should have a method for that, probably
c

cedric

01/17/2018, 8:42 PM
If you want the reverse of
isAssignableFrom
, just reverse the arguments
c

ClaudiuB

01/17/2018, 8:43 PM
I want it but kotlin-code only. I was at the
isAssignableFrom
an hour and something ago
c

cedric

01/17/2018, 8:43 PM
value::class.java.isAssignableFrom...
k

kevinmost

01/17/2018, 8:44 PM
hm yeah, I don't see anything on
KClass
like
isAssignableFrom
c

ClaudiuB

01/17/2018, 8:44 PM
Think I found a way kotlin-only
let me run the debugger!
c

cedric

01/17/2018, 8:45 PM
Just run the REPL
c

ClaudiuB

01/17/2018, 8:45 PM
infix fun <PossibleSuperClass> KClass<out Any>.instanceof(clazz: PossibleSuperClass)
        : Boolean where PossibleSuperClass : KClass<out Any> {
    return clazz.nestedClasses.contains(this)
}
oh wait, maybe that's something else, thought it was a metaphorical
nestedClass
, like nested inside the inheritance hierarchy of the class
k

kevinmost

01/17/2018, 8:46 PM
that isn't what you want, yeah
c

ClaudiuB

01/17/2018, 8:48 PM
infix fun <PossibleSuperClass> KClass<out Any>.instanceof(clazz: PossibleSuperClass)
        : Boolean where PossibleSuperClass : KClass<out Any> {
    return clazz.isInstance(this)
}
k

kevinmost

01/17/2018, 8:49 PM
are you expecting
Int::class instanceof Number::class
to return true there?
c

ClaudiuB

01/17/2018, 8:49 PM
But if you end up processing classes in a programmatic way, you can't use
as
or
as?
anymore
assuming
Int : Number
, i hope so
k

kevinmost

01/17/2018, 8:50 PM
it won't, because you're asking if
KClass<Number>
is an instance of
Int
Int::class.isInstance(3)
would be true
Int::class.isInstance(Number::class)
would not
KClass::class.isInstance(Number::class)
would be true
because
Number::class
is a
KClass<Number>
, which makes it an instance of
KClass
c

ClaudiuB

01/17/2018, 8:52 PM
ok but then there isn't a way I guess?
k

kevinmost

01/17/2018, 9:00 PM
you could manually write a function that checks
superTypes
recursively maybe
There's
allSupertypes
that flattens out the hierarchy for you into one list, but it's JVM-only, haha
c

ClaudiuB

01/17/2018, 9:10 PM
Hmm, I'll try with
superTypes
, thanks for the idea. Maybe I can figure it out without JVM after all!
Thanks for the idea, found out about
KClass#starProjectedType
which returns
KType
, which has
isSubtypeOf
. Method is
infix fun <PossibleSuperClass> KClass<out Any>.instanceof(clazz: PossibleSuperClass)
        : Boolean where PossibleSuperClass : KClass<out Any> {
    return this.starProjectedType.isSubtypeOf(clazz.starProjectedType)
}
And the checks

https://i.imgur.com/uLNxG3Z.png

m

mwerschy

01/17/2018, 9:21 PM
What's the point of doing this in pure Kotlin? Neither of the other targets support the required reflection mechanisms so you'll be bound to the JVM anyway.
c

ClaudiuB

01/17/2018, 9:23 PM
Won't Kotlin ship with it's own VM eventually?
VM that will hopefully implement natively the api at the time?
m

mwerschy

01/17/2018, 9:26 PM
Haven't seen anyone say that's a goal. Source?
Pretty sure someone from Kotlin/Native explicitly said they aren't looking to add their own VM to that so would have to be a new target.
c

ClaudiuB

01/17/2018, 9:42 PM
Hmm, okay, maybe
Kotlin/Native
is what I meant, forget about the VM thing. But Kotlin/Native would still have to implement stuff like
KType
and its functions, right?
c

cedric

01/17/2018, 9:43 PM
I’m still not sure what you’re trying to achieve that’s not already covered by
is
and
as
c

ClaudiuB

01/17/2018, 9:43 PM
Or is
KType
a Kotlin class used as an umbrella thing just for Kotlin + JVM together?
k

kevinmost

01/17/2018, 9:46 PM
@cedric he's trying to determine if one
KClass
instance is a supertype of another, basically
c

ClaudiuB

01/17/2018, 9:46 PM
Cedric, if I try to use
x is y::class
or through the type, it complains. if
y : KType
and try
x is y
it complains, it only works with Real Types, like
OutOfMemoryException
, not
platformUiException::class
k

kevinmost

01/17/2018, 9:46 PM
is
and
as
cover it when you know the types statically
c

ClaudiuB

01/17/2018, 9:46 PM
yes, I guess
static types
better describes it
k

kevinmost

01/17/2018, 9:47 PM
these are dynamic class instances so if I'm understanding his problem correctly, it's exactly why you can't do something like
Class<?> type = Foo.class;
if (myFoo instanceof type) { ... }
in Java
c

cedric

01/17/2018, 9:47 PM
Ah ok
k

kevinmost

01/17/2018, 9:48 PM
unfortunately there's no platform-agnostic
myKClass.isAssignableFrom(otherKClass)
, you have to go through the
.java
extension and get a regular
Class
instance for that
c

ClaudiuB

01/17/2018, 9:48 PM
The thing I posted seemed to work, is that interracting with the JVM? Only uses
KClass
and
KType
// e.g. object::class instanceof Activity::class
infix fun <PossibleSuperClass> KClass<out Any>.instanceof(clazz: PossibleSuperClass)
        : Boolean where PossibleSuperClass : KClass<out Any> {
    return this.starProjectedType.isSubtypeOf(clazz.starProjectedType)
}

// e.g. object instanceof Activity::class
infix fun <PossibleSuperClass> Any.instanceof(clazz: PossibleSuperClass)
        : Boolean where PossibleSuperClass : KClass<out Any> {
    return this::class instanceof clazz
}
m

mwerschy

01/18/2018, 6:27 AM
c

ClaudiuB

01/18/2018, 9:12 AM
Alright, but we have
KClass#superTypes : List<KType>
which we could use instead 🤔 Flatmap it to a boolean maybe?
g

gildor

01/21/2018, 3:57 AM
@ClaudiuB Such thing that you trying to implement make sense, but not sure that it will work on K/N, maybe you should ask in #kotlin-native about real platform agnostic solution or just open an issue about this case