推断的类型为String,但未预期

时间:2019-01-11 12:38:09

标签: generics kotlin

下面的代码无法编译,并出现以下错误:

Error:(28, 61) Type mismatch: inferred type is String but Nothing was expected

我不清楚为什么会这样。我想要达到的目的是让filterMap采取任何类型的过滤器并将其应用于传入的数据。正如您从用于测试的数组中看到的:arrayListOf("Message1", 1, 'C')。反正有实现这一目标的方法吗?我可以通过指定MutableMap<Filter<Any>, String>来解决它,但这意味着我的过滤器也必须是(Any) -> Boolean

类型
class Filter<Q> (val predicate: (Q) -> Boolean, val isEnabled: Boolean) {

        constructor(predicate: (Q) -> Boolean) : this(predicate, false)

        override fun equals(other: Any?): Boolean {
            if (other == null || other !is Filter<*>) {
                return false
            }
            return isEnabled == other.isEnabled && predicate == other.predicate
        }

        override fun hashCode(): Int {
            return 0x31 xor predicate.hashCode() xor isEnabled.hashCode()
        }
}

val filterMap: MutableMap<Filter<*>, String> = HashMap()

fun main(args: Array<String>) {
    val messages = arrayListOf("Message1", 1, 'C')
    val isMessage1: (String) -> Boolean  = { it == "Message1" }
    val isMessage1Filter = Filter(isMessage1)


    filterMap.put(isMessage1Filter, "Matched Message1")

    messages.forEach { message ->
        filterMap.filterKeys { it.isEnabled || (it.predicate(message)) }
                .forEach {
                    it.value.forEach {
                        println(it)
                    }
          }
     }
}

1 个答案:

答案 0 :(得分:2)

过滤器的定义为星形投影:Filter<*>,当您从地图上获取函数时,该函数会生成函数(Nothing) -> Boolean

val pred = it.predicate //inferred type: (Nothing) -> Boolean 

这就是为什么编译器不接受String作为参数。

此外,您的messages的类型为ArrayList<Any>,您不能仅将它们用作String

科特林是一种静态类型的语言,它将不允许这些不安全的尝试。

要解决此问题,您可以将所有内容更改为String个泛型:

val filterMap: MutableMap<Filter<String>, String> = mutableMapOf()
val messages = listOf("Message1") 

我知道,这不会满足您的需要,因为您正在寻找通用解决方案。但是随后,您将不得不找到一种方法来安全地投射从非特定集合中获取的实体。