Kotlin Interface supports default implementation. Which implies that we can have a default implementation to all the properties and functions defined in the Interface.
The debate:
Having default implementation on interface is not appreciated by many developers. We are not going to discuss about the pros and cons, but we are more interested in how Kotlin has achieved this.
Note: To keep things simple, the java code blocks used in this article is the decompiled java equivalent of the generated byte-code by the Kotlin compiler.
Let’s get started
Lets take a basic interface Wheels
with default implementations as an example to understand the subject.
interface Wheels {
fun getNumberOfWheels(): Int = 3
}
This interface allows us to skip the implementation in a Kotlin class ????.
class KotlinCar : Wheels
The Java problem
Java forces us to implement all the interface methods even if there are default implementation from the kotlin interface.
Why do we care ?
Though we love kotlin, sometimes we are forced to support legacy code using Java.
So how do we make use of the default implementation in a Java class ?
DefaultImpls ????
The DefaultImpls
is a compiler generated class to hold the default implementations. It can hold default methods for functions and their default parameter values. This is the reason why koltin supports default methods natively. And why it can even work on Java 6.
Fun fact
-
DefaultImpls
can be refered directly from Java sources ????, but not from Kotlin - You are not allowed to name a nested type as
DefaultImpls
in a kotlin interface ????♂️. Check this out -
@JvmName
will not do the trick either
Lets take an example of the Wheels
interface.
The java code (decompiled bytecode) shows that a static class DefaultsImpls
is created. This class will be created only if there is atleast one default implementation.
In this case — the default getNumberOfWheels()
implementation. It is implemented as a static method by the same name, return type, an instance
parameter . $this
references in the function body are refering to the instance
parameter.
So how does kotlin do the trick ?
If an implementing class doesn’t define getNumberOfWheels()
, then the compiler synthetic generates one just pointing to this static method.
What about Java ?
You can implement the same behavior in java by accessing the DefaultImpls
, but you are still forced to implement the methods.
The good news is, you can still access the default implementation by accessing the static class inside the Interface.
Note: This is public only when accessing from Java.Ah! we can also do the same on Kotlin by calling super.$functionName()
, but the DefaultImpls
class is not directly accessible from Kotlin (It’s obvious).
OverKill — Useless implementation
Here is an example of “Just because I can do it, I am doing it”
KotlinCar
and KotlinCar2
generates the same byte code, so make sure you don’t overdo it. Just because you can, doesn’t mean you should ????.
https://proandroiddev.com/kotlin-interface-default-implementation-how-does-it-work-3af5056e0c03