Overloading 'as'


#1

Has there been any thought to allowing for the overloading of the 'as' operator? I know there is some trepedation about this (I remember C++ type conversion overloading could cause some issues), but it's something that seems quite useful. Like other operator overloading, 'as' could map to a method to allow for the type conversion.

One possible implementation would be to have the converter in the class object of the target type. Thus, you still maintain compile-time type safety, since you can look for the converters of the target type.

class SomeType(val data: String) {   class object {   fun as(o: String): SomeType {            return SomeType(o)   }   } }

val text = "some text"
val obj = text as SomeType

Yes, you could just call the converter function directly, but the semantics of the ‘as’ operator are useful and provide for consistent usage.


#2

What's the gain compared to simply implementing the conversion on the class:

val obj = SomeType.fromString(s)

?

Less elegant (you need to come up with a method name) but easier to track down.


#3

Well, think of toString(). This is an arbitrary conversion, but the language and library deems it important to have a standard way to convert to String because there are lots of uses for String representations of objects. What's great is that I'm able to have a method that takes Any, but allows me to get a string when it's useful (say, for logging).

But what makes String special? Aren’t there other types where a similar convention might be useful?

fun sum(vals: List<T>) {   var amt = 0   for (v in vals) {   amt += v as Int   }   return amt }

Thus, I now have a function that can sum any objects that can be represented as an Int, much like Kotlin's string templates can output anything with a toString(). The framework could have certainly required me to call toString, but it's a nice convenience. This just generalizes 'toString()' to types other than String.

#4

fun sum(vals: List<T>) {   var amt = 0   for (v in vals) {   amt += v as Int   }   return amt }

But how do you enforce at compile time that T can be converted to an Int?


#5

This is true. Implementing as such, would likely sacrifice that compile time type checking. At runtime, the as? operator would still be useful.


#6

Preserving statically enforceable type safety should trump other concerns, in my opinion.

Scala hits an interesting middle ground by specifying that there needs to exist an implicit conversion from a type to another without necessarily polluting the type you start with. The downside is that now you have types in one bag and conversions in another bag, which is the reason why the Scala community is so split about implicits when used to do type conversion.

My suggestion (explicitly implementing “fromString()”) preserves type safety but it forces the user to implement the type conversion as part of the type. More explicit, but arguably questionable from a design standpoint.


#7

Hi Jon,

There was (is?) a proposal to add a convert operator (~) to the language that I think would cover your use case.

Conversions are written as “convert” extension functions and then the convert operator will automatically pick the correct convertion as required.

See: http://youtrack.jetbrains.com/issue/KT-1752#comment=27-318887

I really like the idea, but I'm not sure if it is still going to be included as it appears SAM will now be done transparently (~ was going to cover SAM as well I believe).

Cheers,
Andrew