Is it possible to use `when` on a reified generic...
# announcements
s
Is it possible to use
when
on a reified generic type?
Copy code
inline fun <reified F : Foo, reified B : Bar> convert(input: F) : B {
when(B) {
Bar1 -> {}
Bar2 -> {}
}
d
It is possible to use classes:
Copy code
when (T::class) {
    Boolean::class ->
    Float::class ->
    Int::class -> 
    Long::class ->
    String::class ->
    else ->
}
s
oki thanks! Would be interesting to have this implemented with smartcasting etc
m
Does using
is
work? That's generally the way to do class comparisons in
when
, isn't it?
2
t
maybe use "is" ?
s
no, there is no instance of B available
t
indeed you're right, I overlooked it was used as a return type ... but that seems quite backwards to me, and unclean
maybe I can't see the big picture 🙂
s
I'm trying to implement a generic number converting system, so I can do mathematical operations on them
Returning the type of the first number
This is at least what I'm trying to do. Not sure if it would actually works in a favorable way
d
Use a
.let { it as T }
chained to the
when
, and add a surpression for unchecked casts. It works, but it definitely isn't pretty.
s
I'm doing this because of this problem. The mathematical operations work for every number type, except for number. which is kinda frustrating.
m
I'd consider Extension functions over this. Of course if you've already been down that road, then...
s
I'm already doing extension functions. but in a scenario where the types of the numbers are not known. I have a problem. so this is my (not that nice) fix for it
nvm. this won't work either. this would probably cause a stack overflow
d
How about double dispatch, something like this? I only chose to widen because i did not want to write too many overloads.
Copy code
operator fun Number.times(other: Number) = this.widen().let {
    when (it) {
        is Long -> other.times(it)
        is Double -> other.times(it)
        else -> throw Exception()
    }
}

operator fun Number.times(other: Long) = this.widen().let {
    when (it) {
        is Long -> other.times(it)
        is Double -> other.times(it)
        else -> throw Exception()
    }
}

operator fun Number.times(other: Double) = this.widen().let {
    when (it) {
        is Long -> other.times(it)
        is Double -> other.times(it)
        else -> throw Exception()
    }
}

fun Number.widen(): Number = when (this) {
    is Byte, is Short, is Int, is Long -> this.toLong()
    is Float, is Double -> this.toDouble()
    else -> throw Exception()
}
t
yep I would suggest to overload operators as well, much cleaner approach rather than trying to make Kotlin into JavaScript 😉