Kotlin中属性Getter方法引用无法适配自定义函数式接口问题
问题原因
Foo::bar是Kotlin的属性引用,类型为KProperty1<Foo, Bar?>,它本质是一个代表属性的Kotlin反射对象,并非直接对应(Foo) -> Bar?类型的函数。
Kotlin的SAM转换仅支持将函数/方法引用直接适配为自定义函数式接口,属性引用不在自动转换的范围内——因为属性引用本身不是方法,它虽然包含get()方法,但Kotlin不会自动将其包装成你定义的FooBarSelector接口实例。
可选解决方案
除了你提到的两种方式,还可以通过封装转换逻辑来实现更接近需求的写法:
方案1:给函数式接口添加转换方法
在FooBarSelector的伴生对象里定义一个静态方法,专门将KProperty1转换为接口实例:
fun interface FooBarSelector { fun select(foo: Foo): Bar? companion object { // 封装属性引用到接口的转换逻辑 fun fromProperty(property: KProperty1<Foo, Bar?>): FooBarSelector { return FooBarSelector { property.get(it) } } } }
使用时可以直接调用这个方法:
class KotlinClass() { val selector: FooBarSelector = FooBarSelector.fromProperty(Foo::bar) } fun doSomething( selector: FooBarSelector = FooBarSelector.fromProperty(Foo::bar) ) { }
方案2:给KProperty1添加扩展函数
给KProperty1<Foo, Bar?>定义扩展函数,直接转换为FooBarSelector:
// 扩展函数,将属性引用转为目标接口 fun KProperty1<Foo, Bar?>.asFooBarSelector(): FooBarSelector { return FooBarSelector { this.get(it) } }
使用时写法更简洁:
class KotlinClass() { val selector: FooBarSelector = Foo::bar.asFooBarSelector() } fun doSomething( selector: FooBarSelector = Foo::bar.asFooBarSelector() ) { }
这两种方案都保留了自定义接口类型,同时复用了属性引用的写法,比直接写lambda更符合你的需求。
内容的提问来源于stack exchange,提问作者Quinteger
相关产品推荐
相关产品推荐

