Operator overloading is not the same thing as implicit conversion, because it doesn’t work if there isn’t an explicitly overloaded version of the operator.
One reason implicit conversion is a problem is specifically because it conflicts with overloading:
fun foo( bar: Long ) {
println("A")
}
fun foo( bar: Double ) {
println("B")
}
foo( 5 ) // Does this print "A" or "B"? Neither, because it (correctly) won't compile
This problem goes away if there’s another overload of the function:
fun foo( bar: Long ) {
println("A")
}
fun foo( bar: Int ) = foo(bar.toLong()) // Explicitly treat integer as long
fun foo( bar: Double ) {
println("B")
}
foo( 5 ) // Prints "A"
The difference here is that the decision of how to handle the ambiguity is with the developer (and this includes the developer of the standard library), rather than rules that are baked into the language and can’t be changed.
For operators like +
, -
, *
, /
there won’t be big obvious differences because the standard library defines those overloads (which you can also do).
When assigning variables, however, that is lost, but consider this: A variable assignment may actually be a function call, and therefore could be overloaded, so implicit conversions would cause problems.
However, this is not really a big issue because Kotlin can infer variable types. The code that you gave (which doesn’t work)…
val pixelX = 0
val pixelXAsSubPixelPrecision : Double = pixelX
…doesn’t actually have to get much longer when you make it work; you just have to rearrange it…
val pixelX = 0
val pixelXAsSubPixelPrecision = pixelX.toDouble()
It may feel a little awkward coming from other languages (it certainly did to me) but once you get used to it, it’s really not a big deal.
Having no implicit conversion, but operators overloaded in the standard library, works out to be a pretty good balance, is easy to remember, and the behavior is well defined and most importantly unambiguous.