我可以省略Kotlin中不使用的接口方法吗?

guykilcj  于 2022-11-16  发布在  Kotlin
关注(0)|答案(2)|浏览(146)

如果我只对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.")
        }
    })
}
5ssjco0h

5ssjco0h1#

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

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方法的实现。

knpiaxh1

knpiaxh12#

我想出了以下有趣的方法。
下面的函数使用一个dynamic proxy来“具体化”一个接口,并且只使用所需的方法来修补它。未被修补的方法将只返回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>)。
我之所以提供这种方法,是因为它可能对某些用例感兴趣,如果这让您感到意外,我很抱歉。

相关问题