Can I omit the interface methods I do not use in Kotlin?

后端 未结 2 1516
再見小時候
再見小時候 2020-12-15 02:37

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 Ev         


        
2条回答
  •  再見小時候
    2020-12-15 03:20

    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  Any.materialize(): T = materialize(T::class.java, this)
    
    fun  materialize(i: Class, 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()
    
        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).

    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.

提交回复
热议问题