最近看到一种很有意思的类写法:
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会提示如下:

Function1接口的invode方法,所以我之前的描述是有问题的:ExampleProxy并不是返回函数定义(String) -> Unit,而是实现了接口Function1。换一个角度看,kotlin内形如(R,..)->T的函数类型等价于FunctionX,R,..参数数量即为X:

Functions.kt可以看到最多支持到22个参数函数类型定义,只是写法...确实很简单粗暴...
实现FunctionX的类可以做什么?
回到正题,前文实现了Function1的ExampleProxy类,其每个实例对象即代表一个函数引用。由此我们可以在类构造函数内传入相同函数类型定义的函数引用,实现函数层面的动态代理。
函数级代理
定义一个类A:
class A {
fun printInfo(s: String) {
println("I'm $s")
}
}
以被代理函数printInfo的引用作为构造参数实例化出一个ExampleProxy类的对象printInfoProxy。printInfoProxy("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类型的函数。