gpt4 book ai didi

generics - Kotlin 强制可空泛型类型转换为同一泛型类型的不可空泛型?

转载 作者:IT老高 更新时间:2023-10-28 13:45:16 26 4
gpt4 key购买 nike

首先我只想指出,我知道 Force a null into non-nullable typeKotlin Generics and nullable Class type但我不认为这些问题和我的一样(如果我错了,请纠正我)。

背景

我正在开发一个名为 Awaitility 的库简而言之,它旨在等待谓词评估为真。 Kotlin API提供了一种编写这样的表达式的方法:

// Create a simple data class example
data class Data(var value: String)
// A fake repository that returns a possibly nullable instance of Data
interface DataRepository {
// Invoked from other thread
fun loadData() : Data?
}
val dataRepository = .. // Implementation of DataRepository

// Now Awaitility allows you to wait until the "value" in Data is equal to "Something"
val data : Data = await untilCallTo { dataRepository.loadData() } has {
value == "Something"
}

这是因为 has 返回 false 如果 dataRepository.loadData() 返回 null 并且从不调用提供的如果 datanull,则接收函数 ({ value == "Something"})。如果条件不满足,Awaitility 也会抛出异常,因此我们知道从表达式返回的内容是 Data 类型(而不是 Data? ) 如您在示例中所见。

has函数是这样实现的:

infix fun <T> AwaitilityKtUntilFunCondition<T?>.has(pred: T.() -> Boolean) = factory.until(fn) { t: T? ->
if (t == null) {
false
} else {
pred(t)
}
} as T

其中 AwaitilityKtUntilFunCondition 如下所示:

data class AwaitilityKtUntilFunCondition<T> internal constructor(internal val factory: ConditionFactory, internal val fn: () -> T?)

(如果需要,您还可以找到 ConditionFactory here)

虽然上面的示例在传递给 untilCallTo 的 lambda 返回可空类型 (Data?) 时效果很好,但如果我们将其传递给不可为空的类型,则无法编译类型(即 Data)。例如,如果我们简单地将存储库修改为如下所示:

interface DataRepository {
// Invoked from other thread
fun loadData() : Data // Notice that loadData now returns a non-nullable type
}

如果我们然后尝试与上一个示例相同的等待表达式:

val data : Data = await untilCallTo { dataRepository.loadData() } has {
value == "Something"
}

我们会得到一个编译时错误:

Error:(160, 20) Kotlin: Type mismatch: inferred type is AwaitilityKtUntilFunCondition<Data> but AwaitilityKtUntilFunCondition<Data?> was expected
Error:(160, 68) Kotlin: Type inference failed. Please try to specify type arguments explicitly.

这是(当然)正确的!

问题

我想要做的是以某种方式修改 has 方法以强制返回类型始终是作为参数传入的类型的不可空等价物(可以是可空的或不可为空)。我试图做这样的事情(这是行不通的):

infix fun <T, T2> AwaitilityKtUntilFunCondition<T>.has(pred: T2.() -> Boolean): T2
where T : Any?, // Any? is not required but added for clarity
T2 : T!! // This doesn't compile
= factory.until(fn) { t: T ->
if (t == null) {
false
} else {
pred(t as T2)
}
} as T2

由于 T2 : T!! 导致无法编译,但我希望它表明了我的意图。 IE。我想以某种方式将 T2 定义为:

  1. 如果 T 可以为空,则 T 类型的不可为空等效项
  2. 如果 T 是不可为空的类型,则与 T 相同

这在 Kotlin 中可行吗?

更新:

我在 Awaitility 项目中创建了一个名为 has-with-non-nullable-type 的分支,您会在其中看到我在文件 KotlinTest 中讨论的编译时错误。 .这就是我想要编译的。您可以使用以下方法克隆它:

$ git clone https://github.com/awaitility/awaitility.git

更新 2:

我已添加 gist我认为在不使用任何依赖项的情况下演示了问题。

最佳答案

我创建了一个最小的例子来实现你想要的:

fun <T: Any> test(t: T?): T {
// ...
return t as T
}

您为 T 定义了一个上限 Any,因此它不能为 null。对于参数 t,您使用类型 T?。最后你返回 t 转换为 T

示例:

val a: String = test("Hello")
val b: String = test(null)

关于generics - Kotlin 强制可空泛型类型转换为同一泛型类型的不可空泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54249929/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com