Extending general type


#1

How can I implement the below extension to all types of numbers?

fun Int.square(): Int {
  return this * this
}

fun main(){
  println(5.square()) //prints 25
}

In Rust the below is the way to do it:

mod foo {
    pub trait SquareExt {
        fn square(self) -> Self;
    }

    use std::ops::Mul;
    impl<T> SquareExt 
    for T 
    where  T: Mul<Output = T> + Copy
    {
        fn square(self) -> T { self * self }
    }
}

fn main() {
    use foo::SquareExt;
    println!("{}", 5.1.square());     // prints 26.009999999999998
}

#2

You can’t. For some reason ( I guess it has to do with how the jvm handles primitives) Number itself does not have any operators. The only way to implement a function for all Numbers is either copy the function for each type or use a when expression (with one case per type). Neither of those versions allows for new Number classes created by others.

One possible solution of the future would be to use type classes. But this is only a KEEP so there is no guarantee when or if this will be part of Kotlin.


#3

I think there’s a different * operator for each type, and deciding which one to use is done statically (at compile time) — which can only be done if the exact types are known.

(As Wasabi375 says, this may be due to how primitives are handled — there probably is no object that dynamic dispatch could be applied to. And even if there were, every Number implementation would have to provide operators that could add/subtract/multiply/divide every other Number implementation, which is clearly impractical given that you can write your own implementations!)

Expressions such as:

(1 as Number) * (2 as Number)

don’t compile, for the same reason.

If you didn’t care about precision, you could take advantage of the fact that Number has methods like toDouble():

fun Number.square(): Double = toDouble() * toDouble()

…but that is of course just an ugly hack. A good general solution seems impossible.