What if I am only interested in onSee
and do not care for other events? Can I at least omit the methods that have no return values?
interface EventHandler
{
fun onSee()
fun onHear()
fun onSmell()
fun onTouch()
fun onAwake()
fun onSleep()
}
fun addEventHandler(handler:EventHandler)
{
}
fun Main()
{
addEventHandler(object:EventHandler
{
override fun onSee()
{
print("I see.")
}
})
}
Yes, it is mandatory to implement all the methods in a class that implements an interface until and unless that class is declared as an abstract class. Implement every method defined by the interface.
However, you can avoid this by following the below approach: Declare the missing methods abstract in your class. This forces you to declare your class abstract and, as a result, forces you to subclass the class (and implement the missing methods) before you can create any objects.
If you have default method in an interface, it is not mandatory to override (provide body) it in the classes that are already implementing this interface. In short, you can access the default methods of an interface using the objects of the implementing classes.
Yes, you can write an interface without any methods. These are known as marking interfaces or, tagging interfaces. A marker interface i.e. it does not contain any methods or fields by implementing these interfaces a class will exhibit a special behavior with respect to the interface implemented.
Sure, that is possible! you can implement one interface method when you extend it, all you have to do is to provide a default implementation for the other methods in the interface declaration
interface EventHandler {
fun onSee()
fun onHear() { /* default implementation */ }
fun onSmell(){ /* default implementation */ }
fun onTouch(){ /* default implementation */ }
fun onAwake(){ /* default implementation */ }
fun onSleep(){ /* default implementation */ }
}
Now when you create an instance of this interface you only need to provide a compulsory implementation for onSee()
method, rest are optional
If you're not the author of the original interface You could extend the original interface and provide a default implementation for the methods you want
interface OnSeeEventHandler: EventHandler {
override fun onHear() { /* default implementation */ }
override fun onSmell(){ /* default implementation */ }
override fun onTouch(){ /* default implementation */ }
override fun onAwake(){ /* default implementation */ }
override fun onSleep(){ /* default implementation */ }
}
And use the OnSeeEventHandler
to provide only onSee
method imeplementation
I came up with the following, somewhat p̶e̶r̶v̶e̶r̶s̶e̶ interesting approach.
The function below uses a dynamic proxy to "materialize" an interface and patch it with only the needed methods. Methods that are not patched will just return null
or Unit
, depending on the return type.
import java.lang.reflect.Proxy.newProxyInstance
inline fun <reified T> Any.materialize(): T = materialize(T::class.java, this)
fun <T> materialize(i: Class<T>, x: Any = object {}): T {
@Suppress("UNCHECKED_CAST")
return newProxyInstance(i.classLoader, arrayOf(i)) { _, m, args ->
x.javaClass.methods
.asSequence()
.filter {
it.name == m.name
&& it.parameterTypes!!.contentEquals(m.parameterTypes)
}
.map {
it.invoke(x, *args.orEmpty())
}.firstOrNull()
} as T
}
It can then be used as follow, given an interface Foo
and an anonymous object that contains only an implementation of its qux()
function:
interface Foo {
fun bar()
fun baz(): String
fun qux(s: String): String
}
fun main(vararg args: String) {
val foo = object {
fun qux(s: String): String {
return "Returned from qux: $s"
}
}.materialize<Foo>()
println(foo.bar()) // void no-op, prints "kotlin.Unit"
println(foo.baz()) // no-op with return value, prints "null"
println(foo.qux("Hello")) // prints "Returned from qux: Hello"
}
Disclaimer
- Using this, you lose all compile-time checking as everything is resolved at runtime.
- Some things are not covered by this implementation (e.g. interface default methods).
- Performance is not taken into account at all.
- Requires the
kotlin-reflect
dependency.- Today is my second day learning Kotlin, so there might be any number of unaddressed edge cases and bugs.
I would not use this myself in most cases, and will continue to hold out for a Kotlin construct that supports partial interface implementations (like TypeScript's
Partial<T>
).I'm only providing this approach because it might be of interest for some use cases, and I'm sorry if this made your eyes bleed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With