I am surely can’t understand a thing in your question. Number is a superclass for different numeric classes like Double, BigDecimal or even AtomicInteger. There is a reason why it is not comparable: comparison works different for different numeric representations, and you can’t predict how it will behave for custom numbers. If you are sure that all numbers in your program will behave as Doubles, you can add some useful extension functions for that. val a: Number = 0 is better than val a: Any = 0 because in first case you could call specific Number methods for a, in second cases it will be just generic object. In both cases actual object type will be Int. As for elvis operator ?:, I don’t undersnad what it means in your code. In Kotlin elvis is used only for nullables.
Literally, a number can be compared to another number by its value.
just like 5 > 2.1
If you just want to represent a value, You can only implement Value interface.
I think the name of Number class is not a good name for represent its usage.
Please see the description of elvis operator in kotlin. You are trying to use it like in groovy, where groovy truth states that 0 == null, but event in groovy it does not make sense. In Kotlin it does not work at all. It probably compiles, but your value is never null so it does nothing.
the value of Double and value of BigDecimal are very different values. There is no universal way to compare them. In my programs I frequently extend some of number properties like arithmetic operations, but it is not universal.
They are already comparable. Though If you use a Number as a compile-time type, you do not know what specific implementation it will use. You can check it in run-time if you want like that:
fun Number.compareTo(bd: BigDecimal): Int{
return when(this){
is BigDecimal -> this.compareTo(bd) //using kotlin implicit cast
else -> this.toDouble().compareTo(bd.toDouble())
}
}
I think the compiler gets confused because 0.1 is a primitive type. Even in the following case (which makes a bit more sense), the inferred type is Any:
val x: Int? = 0
val a = x ?: 0.1
But if you add an explicit type, it is not a problem to have a be a Number:
val x: Int? = 0
val a: Number = x ?: 0.1
I believe the compiler can be smarter here (if the type of the left operand of ?: is a nullable type, as a non-nullable type does not make sense in combination with ?:), and infer Number. You might want to create an issue in YouTrack if there is none for it yet.
The name inherits Java Number. So no freedom there. I think that problem of comparison different numbers could be partially or completely solved by type-classes.
As for custom usage, you can write your own abstraction on top of numbers. For example I have an interface called Value that could wrap numbers, strings, booleans and Instants. Previously I was using a custom-made comparator for them using type of first argument to perform comparison, but I had to remove it since it basically violates comparable contract (should be commutative). So no I use external comparing function.
I do not know the type inference algorithm, but it looks like that it does not select Number because the subclasses also implement Comparable at the same inheritance level. I still feel that Number could be inferred, because Comparable<Int> and Comparable<Double> are not candidates because they are not implemented by both Int and Double. But somebody with more knowledge about the type inference has to provide the conclusive answer.
But this is all nitpicking about compiler behavior. What is the realistic problem you are trying to solve?