Kotlin:内联 lambda 和重载解析歧义

问题描述 投票:0回答:2

我有一个简单的工厂模式,其中的实现是通过重载解析来确定的。问题是 Kotlin 编译器抱怨内联 lambda 的“重载解析歧义..”。

class Foo(){
    companion object Factory {
        fun create(x: Int, f: (Int) -> Double) = 2.0
        fun create(x: Int, f: (Int) -> Int) = 1
    }
}

fun main(args:Array<String>){
    val a =  Foo.create(1,::fromDouble) //OK
    val b =  Foo.create(1,::fromInt)  //OK
    val ambiguous =  Foo.create(1){i -> 1.0}  //Overload resolution ambiguity?
}


fun fromDouble(int:Int)  = 1.0
fun fromInt(int:Int)  = 1

Kotlin 编译器如何解决重载决策以及为什么内联 lambda 被认为是不明确的?

lambda kotlin overload-resolution
2个回答
5
投票

Kotlin 编译器仅解析每个表达式一次。 因此,当编译器开始解析 lambda 表达式时,它应该知道 lambda 参数的类型。 因为这个编译器应该选择方法之一

create
before 它开始查看 lambda 内部。

示例:

fun foo(f: (Int) -> Int) = 1
fun foo(f: (String) -> String) = ""
val bar = foo { 
   println(it) 
   5
}

这里我们无法选择其中一个函数

foo
,因为它们中没有一个比另一个更具体,因此我们无法开始解析 lambda 表达式,因为我们不知道
it
的类型。

在您的示例中,理论上可以在选择特定函数之前开始解析 lambda,因为对于所有潜在函数,lambda 参数的类型都是相同的。但这是一个不平凡的逻辑,可能很难实现。


0
投票

对于 2023 年遇到此问题的其他人,有一种解决方法可以让 Kotlin 在解决重载时查看 lambda 返回类型(通常不会这样做)。

此处所示,您必须选择实验类型推断并相应地注释方法:

import kotlin.experimental.ExperimentalTypeInference

@OptIn(ExperimentalTypeInference::class) // Can be done per method, class or file
@OverloadResolutionByLambdaReturnType
fun bar(f: () -> Int): String {
    return "${f()}"
}

fun bar(f: () -> String): String {
    return f()
}

fun main() {
    println(
        bar {
            3
        }
    )
}
© www.soinside.com 2019 - 2024. All rights reserved.