https://kotlinlang.org logo
Title
d

dagguh

11/08/2018, 4:35 PM
In library development, compatibility is key. So if you expose an interface to implement (SPI), it’s important not to break implementations all the time. So if you need to add a new method to an interface, you cannot simply leave it unimplemented, because it will fail after recompile. Java 8 solves it with default methods. In order to produce Java 8 default methods from Kotlin, you gotta use
@JvmDefault
. But then the library consumers still fail recompilation:
Inheritance from an interface with ‘@JvmDefault’ members is only allowed with -Xjvm-default option
. Did you ever encounter this? If so, what did you do? Added a new library requirement and released a major (SemVer backwards incompatible) version?
l

louiscad

11/08/2018, 4:58 PM
d

dagguh

11/08/2018, 5:43 PM
Yes, this page explains how to produce such interfaces, but doesn’t explain the additional requirement for the implementations.
e

elizarov

11/08/2018, 6:05 PM
Extension functions in Kotlin for most part abolish the need to add more methods to interfaces in future updates, so we hardly ever encounter this problem.
d

dagguh

11/15/2018, 3:21 PM
@elizarov according to the docs and tests, extension functions are resolved statically. Interface methods are resolved dynamically and this is critical for our use case. Polymorphism is why we expose an interface (SPI) in the first place.
e

elizarov

11/15/2018, 3:25 PM
That is exactly what I meant when I said “hardly ever” 🙂 If you analyze large JDK interfaces with tons of methods, then most of those methods do not benefit from polymorphism and would work just as well as extensions. Situations where you truly need to add a new polymorphic method to an existing interface are quite rare in practice and often, if this interface had been widely adopted (there are delegate/adapter impls, etc) adding Java default method is not viable solution either.
I does happen, though. So java default methods do have their uses.
d

dagguh

11/15/2018, 3:35 PM
Indeed. It's especially useful when you want to be nice to your API consumers and SPI producers and not break them unless absolutely necessary. Even if the interfaces have adapters and delegates, default methods help. Adapters are just another API consumers and delegates are yet another SPI implementors.