我可否省略不在 Kotlin 使用的接口方法?

如果我只对 onSee感兴趣,而不关心其他事件怎么办?至少可以省略没有返回值的方法吗?

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.")
}
})
}
19830 次浏览

当然,这是可能的!当你扩展一个接口方法时,你所要做的就是在接口声明中为其他方法提供一个默认的实现

interface EventHandler {
fun onSee()
fun onHear() { /* default implementation */ }
fun onSmell(){ /* default implementation */ }
fun onTouch(){ /* default implementation */ }
fun onAwake(){ /* default implementation */ }
fun onSleep(){ /* default implementation */ }
}

现在,当您创建这个接口的一个实例时,您只需要为 onSee()方法 休息是可选的提供一个强制实现

如果您不是原始接口的作者 您可以扩展原始接口并为所需的方法提供默认实现

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 */ }
}

并且使用 OnSeeEventHandler只提供 onSee方法实现

我想出了下面这个比较有趣的方法。

下面的函数使用 动态代理服务器“实体化”一个接口,并只用所需的方法对其进行修补。未打补丁的方法将根据返回类型返回 nullUnit

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
}

然后,给定一个接口 Foo和一个只包含其 qux()函数实现的匿名对象,就可以按照以下方式使用它:

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"


}

免责声明

  • 使用这种方法,您将失去所有编译时检查,因为所有问题都是在运行时解决的。
  • 这个实现没有涵盖某些内容(例如接口默认方法)。
  • 完全没有考虑性能。
  • 需要 kotlin-reflect依赖项。
  • 今天是我学习 Kotlin 的第二天,所以可能会有很多未解决的边缘案例和 bug。

我自己大多数时候都不会用这个 案例,并将继续坚持 Kotlin 的建设,支持部分 接口实现(如 TypeScript 的 Partial<T>)。

我只是提供 这种方法是因为它可能对某些用例有意义,而我 如果这让你的眼睛流血了,我很抱歉。