kotlin

kotlin 函数级代理模式

2018-09-20  本文已影响0人  capcNote

最近看到一种很有意思的类写法:

class ExampleProxy(private val method: (String) -> Unit) : (String) -> Unit {
    override fun invoke(param: String) {
        println("proxy do something...")
        method(param)
    }
}

定义了一个ExampleProxy类,返回类型是一个函数类型定义(String) -> Unit。类内重载了invoke操作符,参数类型必需和类返回的函数类型定义中的参数类型是一致的(有点绕)。

FunctionX

注意到,如果类返回类型是函数定义的话,invode方法是必需重载的。可以看到如果注释掉invoke方法,IDE会提示如下:

根据提示可以看出,重载的是kotlin包内Function1接口的invode方法,所以我之前的描述是有问题的:ExampleProxy并不是返回函数定义(String) -> Unit,而是实现了接口Function1。换一个角度看,kotlin内形如(R,..)->T的函数类型等价于FunctionXR,..参数数量即为X 点进Functions.kt可以看到最多支持到22个参数函数类型定义,只是写法...确实很简单粗暴...
实现FunctionX的类可以做什么?

回到正题,前文实现了Function1ExampleProxy类,其每个实例对象即代表一个函数引用。由此我们可以在类构造函数内传入相同函数类型定义的函数引用,实现函数层面的动态代理。

函数级代理

定义一个类A

class A {
    fun printInfo(s: String) {
        println("I'm $s")
    }
}

以被代理函数printInfo的引用作为构造参数实例化出一个ExampleProxy类的对象printInfoProxyprintInfoProxy("abc")方式的调用效果等同于printInfoProxy.invoke("abc")。执行main方法:

fun main(args: Array<String>) {
    val printInfoProxy = ExampleProxy(A()::printInfo)
    printInfoProxy("abc")
}

打印结果:

proxy do something...
I'm abc

可以看到,由此实现了代理的效果。
实际上这是一种形式受限的动态代理,ExampleProxy只可以代理(String) -> Unit类型的函数。

上一篇 下一篇

猜你喜欢

热点阅读