Котлин контракты: ссылка не-ноль из двух свойств - PullRequest
0 голосов
/ 12 декабря 2018

Скажем, у меня есть такой класс:

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" } } 
}

Этот класс гарантирует, что если path != null тогда и только тогда, когда url != null

Котлин заключает контракт кажетсяспособ рассказать компилятору об этих видах отношений.Возможен ли вышеупомянутый инвариант для моделирования с контрактами Котлина?

Мой конечный результат - позволить коду наподобие следующего компиляции:

val x = URLAndPath(URL("http://example.org/"), "index.html")
if(x.path != null) {
    // currently: Error: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type URL?
    println(x.url.toURI())
}

1 Ответ

0 голосов
/ 12 декабря 2018

Это кажется невозможным в Kotlin 1.3, поскольку контракты могут быть только для функций верхнего уровня, а не для методов.

Например,

@ExperimentalContracts
data class NullableString(val s: String?) {

    fun isNotNull(): Boolean {
        contract {
            returns(true) implies (this@path != null)
        }
        return path != null
    }
}

не компилируется:

Error:(16, 8) Contracts are allowed only for top-level functions
Error:(17, 39) Unresolved reference: @path
Error:(19, 15) Unresolved reference: path
...