Kotlin中如何将函数接收者类型与SAM接口搭配使用
Kotlin SAM接口支持接收者类型lambda的实现方案
核心修改逻辑
只需要调整SAM接口中抽象方法的定义,把原本的入参receiver: T改成方法的接收者即可,Kotlin的SAM转换机制会自动完成lambda的this绑定。
修改后的完整代码
// 1. 修改SAM接口的抽象方法为带接收者的扩展函数 fun interface Delegator <T> { fun T.delegate() } fun <T> invokeWithDynamicReceiver(receiver: T, fn: T.() -> Unit) = receiver.fn() // 2. 调整调用delegate方法的方式,用接收者触发调用 fun <T> invokeWithSamInterface(receiver: T, fn: Delegator<T>) = receiver.fn.delegate() fun dynamicReceiver() { invokeWithDynamicReceiver("Foo") { length } // 原有动态接收者写法不变 invokeWithSamInterface("Foo") { length } // 现在可以直接通过this访问接收者成员,无需it }
原理解释
- 原有写法中
delegate(receiver: T)是普通成员方法,receiver是方法的第一个入参,因此SAM转换后的lambda只会把参数暴露为默认的it变量。 - 把方法声明为
T.delegate()扩展方法后,Kotlin会把这个方法的接收者和lambda的上下文this做绑定,行为和原生的带接收者函数类型T.() -> Unit完全一致。 - 该写法兼容Java侧调用:带接收者的Kotlin扩展方法在字节码中会被编译为普通静态方法,第一个参数就是接收者对象,和原有接口的Java调用签名完全一致,不会产生兼容性问题。
内容的提问来源于stack exchange,提问作者Tuomas Toivonen
相关产品推荐
相关产品推荐

