java Kotlin:如何显式指定lambda的实际类型?
如何在Kotlin中显式指定lambda的实际类型
这是必要的,因为如果我有两个函数采用相似的lambda,例如
fun use(block: Context.() -> Boolean)
@JvmName("use2") fun use(block: Context.() -> Unit)
我希望能够使use2
调用正则(布尔)use
,即
@JvmName("use2") fun use(block: Context.() -> Unit) = use { block(); true }
这类似于可以显式指定SAM类型的方式,例如:
Runnable { println("hello") }
如何对Kotlin lambda类型执行相同操作
这是我想出的解决问题的方法,但我想知道是否有更好/更干净的方法
@JvmName("use2") fun use(block: Context.() -> Unit) = use({ block(); true } as (Context.() -> Boolean)})
# 1 楼答案
您可以使用
@OverloadResolutionByLambdaReturnType
注释,但这是一个实验性功能,因此需要添加@OptIn(ExperimentalTypeInference::class)
。此外,还应该显式指定返回类型# 2 楼答案
我已经做到了:
删除强制转换或
: String
类型注释将使其无法编译。IntelliJ IDEA还错误地报告演员阵容是不必要的(note that this isn't the first time IntelliJ is wrong)注意,我已经将lambda的类型从
Context.() -> Boolean
更改为(Context) -> Boolean
,因为我认为没有明确指定接收器类型的方法。但这不会影响过载解决方案如果您真的想使用接收器类型为
Context
的东西,可以使用匿名函数:我认为这是一种更好的编写
use2
的方法,但请注意,匿名函数不同于lambda in many ways# 3 楼答案
我认为有两个选项可以让代码更加清晰:泛型和函数接口。它们也可以结合在一起
选项1:泛型(*见下文更新)
不要指定返回值,而是使用泛型。对于所有交互,我们只能有一个功能:
如果
block
不返回布尔值,您还希望返回到默认值true
。我们也可以这样做:*UPDATE实际上,泛型不是必需的,因为
use(...)
函数总是返回布尔值,而不是lambda的结果这里有一个非泛型的
use(...)
函数,可以解决“两个函数的jvm签名冲突”的问题:选项2:功能接口
使用functional interfaces——它使lambda的定义更加清晰,并且可以重用
现在关于返回类型没有什么不明确的地方了
use(...)
函数要么接受谓词,要么接受消费者,故事的结尾注意:
with(block) { ... }
(read more about it here)是必需的,因为我们定义的功能接口有接收器泛型+功能接口
我们可以将两者结合起来,以获得两个方面的最佳效果:简洁和清晰: