我正在尝试编写一个扩展函数,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) 我正在尝试编写一个断言函数来检查给定的对象是否属于某个类型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
谁能向我解释一下 KotlincallsInPlace合约的好处是什么?编译器如何利用知道 lambda 函数将被调用的优势?还有,开发商从中得到什么好处?像smartcast之类的?
先感谢您。
假设我有一堂这样的课:
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) 我有一个看起来像这样的函数:
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有办法做到这一点吗?