示例:

sealed interface Foo<out T> {
    val value: T
}

data class Bar<out K: List<Int>>(override val value: K): Foo<K>
    
fun <T> processFoo(foo: Foo<T>) {
    
    when (foo) {
        is Bar -> foo.value.forEach(::println)
    }
}

失败,出现以下错误:

未解析的引用.以下候选人均不适用 由于接收器类型不匹配:

  • kotlin.collections中定义的public inline fun <T> Iterable<TypeVariable(T)>.forEach(action: (TypeVariable(T)) -> Unit): Unit
  • kotlin.collections中定义的public inline fun <K, V> Map<out TypeVariable(K), TypeVariable(V)>.forEach(action: (Map.Entry<TypeVariable(K), TypeVariable(V)>) -> Unit): Unit

为什么这会失败呢?我认为,如果fooBar类型,那么我们就知道TList<Int>的一个子类型.所以我们应该可以在上面拨打forEach.我说错了吗?

推荐答案

我希望如果Foo是Bar类型,那么我们就知道T是List的子类型.所以我们应该可以打电话给每个人.

是的,这是真的.但T也可以实现Map<K, V> at the same time,因为它实现List<Int>(我不知道这种类型,但理论上它可能存在),在这种情况下,您还可以调用此扩展函数:

inline fun <K, V> Map<out K, V>.forEach(
    action: (Entry<K, V>) -> Unit)

查看所有不同的forEachhere.

要具体调用为Iterable定义的forEach,只需执行强制转换:

// could also cast to List<Int> here - that's a completely safe unchecked cast
(foo.value as List<*>).forEach(::println)

另一种 Select 是使用is Bar<*>,但这样做的一个(非常)轻微的缺点是,当<*>foo.value的类型预测为List<Int>时,您会丢失T.你不能在应该是T的地方使用foo.value.

一个人为的例子是:

fun <T> processFoo(foo: Foo<T>): T {
    return when (foo) {
        // you can't return foo.value when you are expected to return T
        is Bar<*> -> foo.value.also { 
            it.forEach(::println) 
        }
    }
}

Kotlin相关问答推荐

在kotlin中使用List(mylist. size){index—TODO()}或Map迭代>

我如何测试一个可组合组件没有显示,但如果它不存在也接受?

某些公共函数显然不能在类实例上访问;Klaxon示例

使用 Kotlin 的 Springboot 中缺少 ResponseEntity 正文属性

可以在没有导入声明的情况下调用 Kotlin 扩展函数吗?

为什么 trySend 会发出假数据?

有没有一种简单的方法可以将数组/列表中的每个元素相互相乘 - Kotlin?

如何将jooq multiset的结果映射到Hashmap(Java Map)?

T except one class

在 Kotlin 中通过反射获取 Enum 值

Map.mapTo 到另一个map

零安全的好处

Kotlin 是如何编译的?

如何从 Firestore 查询中排除元素?

Hilt Activity 必须附加到 @AndroidEntryPoint 应用程序

验证和 DDD - kotlin 数据类

我们如何在Java注释声明中引用Kotlin常量?

IllegalStateException:function = , count = 3, index = 3

将 androidx.constraintlayout:constraintlayout lib 更新到 2.0.2 版本后出现崩溃 isRtl () null 引用

在 Kotlin 中声明 Byte 会出现编译时错误The integer literal does not conform to the expected type Byte