代码之家  ›  专栏  ›  技术社区  ›  dtech Ashtonian

Kotlin契约:两个属性的链接不为空

  •  1
  • dtech Ashtonian  · 技术社区  · 6 年前

    假设我有一门课是这样的:

    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

    Kotlin contracts 似乎是告诉编译器这类关系的方法。上述不变量是否可以用Kotlin契约建模?

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

    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 回复  |  直到 6 年前
        1
  •  1
  •   dtech Ashtonian    6 年前

    这在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