Interesting. We'll look into it. Thanks!
I know this is an old post, but this would be a great addition to kotlin.
Example code would be almost the whole tornadofx project.
So, any update?
It’s not an easy feature, but it’s still on the table, we did some experiments, but some more would be required before we make a decision
My main problem is that implicit interfaces would only be based upon the functions implemented. Especially for single method interfaces this would mean a good probability of name collisions as there is no namespacing in function names themselves.
Since it seems no one had a real example of the problem this solves here is one. For any decent sized project with a handful of dependencies, if you try to type “Pair” in IntelliJ and let it auto complete, chances are high you will see this
This wasn’t even a big project but you see multiple classes that are very similarly implemented (usually having a first and second method/properties like in Kotlin), you could even say they have an implicit interface they implement. Now Kotlin has thankfully added that to its standard library but if for some reason you have to work with these classes and with libraries that expect them, then you have to convert them back and forth all over. This may not be an everyday problem but sure feels like a waste of coding time when you encounter that situation and it really starts breaking the benefits of abstraction when you are talking about 10 different things that are all named Pair and all quack like a Pair.
I like the idea of being explicit about the connections though. @cedricbeust idea of just adding the functionality as something analogous to extension methods/properties seems to fit the bill, if it is possible. Now this may be hard to implement. In the case of most of the Pairs in the picture above, the vast majority of them do not even implement an interface and if you needed to convert things, you may end up having to generate code that either uses constructors and or methods or you may just not be able to do it if constructors and setters are private in favor or using a factory. So there would be limitations on what can be extended.
Must have been a long table, or I wonder whether the feature is still on the table.
I am not sure whether this was mentioned already, this feature exists in Typescript also and it makes working with JS libraries much more natural.
It would be a huge gain for Kotlin JS.
For anyone who’s still interested in this feature, I’d suggest that you either check out KEEP-87 or Arrow with Arrow Meta. Both of which provide compile-time extension interfaces in slightly different ways.
Going by Kotlin’s general idealogy this feature should be as explicit as possible. The syntax I liked the most is this kind of in-place delegation:
class Runner1 : Runnable {
override fun run() = println("go go go")
}
class Runner2 {
fun run(): Unit = println("go go go")
}
fun consumeRunner(runnable: Runnable) = runnable.run()
fun main() {
consumeRunner(Runner1()) // normal invocation
consumeRunner(by!! Runner2()) // structural in-place delegation to Runnable interface, the problem is that target type is not expicitly mentioned
consumeRunner(Runnable by!! Runner2()) // v2 with explicit type
consumeRunner(object : Runnable by!! Runner2()) // syntax useful also for implementing abstract classes
consumeRunner(Runner2() as!! Runnable) // or maybe something like structural casting to Runnable interface
}
!!
syntax would indicate that type is not implemented strictly though common interfaces but by class structure.
While I lik the idea of having an explicit syntax, I don’t like using !! for it.
In Kotlin !! is an operator that can throw a runtime exception.
Here we are talking about a compile-time safe feature though. The compiler should prevent using an incompatible type.
I agree. I just used !!
to indicate that it’s kind of forceful version of normal casting/delegation, but this should never throw runtime exceptions. Some different set of characters or keyword could be used instead.
Any updates here? For instance a recent solution to use Map/Collection as if they had the same super class?