标签: kotlin-contracts

Kotlin 合约不适用于扩展函数中的空检查

我正在尝试编写一个扩展函数,true如果值不null为 0 则返回,并使用契约向编译器保证,如果我返回true,则该值不为空。但是,它似乎不适用于智能投射。当我尝试将值传递给采用非 nullable 的函数时,它仍然无法编译Long

我尝试编译这段代码,但它不起作用。我希望将 a从 aid智能转换为a ,因为合约保证如果返回则传入的值不为空。LongLong?isValidIdtrueLong?

正如您所看到的,该属性是不可变的,所以我认为这不是问题。我还在下面添加了更多代码,因为问题似乎特定于扩展函数。当我将 ID 作为传统参数传递时它会起作用。

fun test() {
    val id: Long? = null //5L
    if (id.isValidID()) {
      // It won't compile because the compiler says that id is a Long?
      // instead of smart casting it to a Long. doWithId requires a Long.
      doWithId(id) 
    }
  }

  fun doWithId(id: Long) {}

  @OptIn(ExperimentalContracts::class)
  fun Long?.isValidID(): Boolean {
    contract { returns(true) …
Run Code Online (Sandbox Code Playgroud)

kotlin kotlin-null-safety kotlin-contracts

9
推荐指数
1
解决办法
454
查看次数

Kotlin 合同:在具体化的类型参数上断言实例

我正在尝试编写一个断言函数来检查给定的对象是否属于某个类型T

@UseExperimental(ExperimentalContracts::class)
inline fun <reified T> assertIsInstance(value: Any?) {
    contract {
        returns() implies (value is T)
    }

    Assertions.assertThat(value).isInstanceOf(T::class.java)
}
Run Code Online (Sandbox Code Playgroud)

该函数使用 AssertJ 来做具体的断言,但我愿意让编译器知道在它执行后,valueis 的类型T是可以进行智能广播的。这似乎不起作用,因为:

Error in contract description: references to type parameters are forbidden in contracts

有没有另一种方法来实现这种行为?这里有什么问题?这最终会成为可能吗?

(使用 Kotlin v1.3)

generics kotlin assertj kotlin-reified-type-parameters kotlin-contracts

7
推荐指数
1
解决办法
1360
查看次数

Kotlin callInPlace 合约有哪些好处?

谁能向我解释一下 KotlincallsInPlace合约的好处是什么?编译器如何利用知道 lambda 函数将被调用的优势?还有,开发商从中得到什么好处?像smartcast之类的?

先感谢您。

kotlin kotlin-contracts

4
推荐指数
1
解决办法
98
查看次数

Kotlin 合约:两个属性的链接非空

假设我有一堂这样的课:

data class URLAndPath(
   val baseUrl: URL,
   val path: String?
) {
    val url get(): URL? =
        try { path?.let { URL(baseUrl, it) } }
        catch(_: Exception) { null }

    init { require(path == null || url != null) { "Invalid URL $baseUrl$path" } } 
}
Run Code Online (Sandbox Code Playgroud)

这个类确保当path != null且仅当url != null

Kotlin 契约似乎是告诉编译器这些关系的方式。上述不变量可以用 Kotlin 合约建模吗?

我的最终结果是让如下代码编译:

val x = URLAndPath(URL("http://example.org/"), "index.html")
if(x.path != null) {
    // currently: Error: Only safe (?.) or non-null asserted (!!.) calls …
Run Code Online (Sandbox Code Playgroud)

kotlin kotlin-contracts

4
推荐指数
1
解决办法
2318
查看次数

Kotlin合约推断返回值而不是参数值

我有一个看起来像这样的函数:

fun MyInput?.toOutput() : Output? {
  if (this == null) return null
  return Output(this.someValue)
}
Run Code Online (Sandbox Code Playgroud)

在我知道我MyInput的非空值的地方(例如,在以a input: MyInput作为参数的方法内部),我希望能够使用input.toOutputas Output代替Output?

我试过使用

contract {
  returnsNotNull() implies (this@toOutput != null)
}
Run Code Online (Sandbox Code Playgroud)

但这意味着倒退。这告诉我,如果toOutput返回非空类型,则我input为非空。我想告诉分析器有关基于参数的返回值的信息。在Java中,我可以org.jetbrains.annotations.@Contract("null -> null ; !null -> !null")用来完成此任务。

Kotlin有办法做到这一点吗?

kotlin kotlin-contracts

3
推荐指数
1
解决办法
74
查看次数