How to write generic code in Kotlin to work with numbers – Double
, Int
, etc.?
Example run it, that doesn’t work, how to fix it?
fun <T> Array<T>.pow2(): List<T> where T : Number {
return this.map { it * it } // <= Error
}
fun main() {
val ints = arrayOf(1, 2, 3)
println(ints.pow2())
val doubles = arrayOf(1.0, 2.0, 3.0)
println(doubles.pow2())
}
I know two solutions a) typecasting it.toDouble()
and b) creating separate method for each type, but don’t like none of it.
UPDATE: To comments below, pointing to similar Java question. Kotlin is not the same as Java, for one difference – Kotlin extension methods resolved at compile time, not runtime as Java instance methods. And also the whole point of Kotlin is to be better than Java, and so, it may have some better ways doing things than Java.
4
Looking at Kotlin generic class to math numbers.
There seems to be no way to do what you want. As the math operators have no relation to Number
.
The only thing you can work with is the toDouble
/ toLong
/ .. operations.
So indeed like you said the only solutions you have is typecasting it.
Kotlin doesn’t provide arithmetic operations for any Number
, only for specific types. It is also not entirely clear how it should work, for example: what should be the resulting type of multiplying a double and integer?
If we create such operator, your code starts to compile and works as expected:
@Suppress("UNCHECKED_CAST")
operator fun <T : Number> T.times(other: T) : T = when (this) {
is Int -> this * other as Int
is Double -> this * other as Double
// ...
else -> throw IllegalArgumentException("Unsupported number types: ${this::class} and ${other::class}")
} as T