问题很简单:(使用 Kotlin 1.3.71)
我有以下类似的数据:
data class Location(val lat: Double, val lng: Double)
我想通过这样的调用来实现类型安全:
val loc = location {
lat = 2.0
lng = 2.0
}
为此,我建立了:
fun location(builder: LocationBuilder.() -> Unit): Location {
val lb = LocationBuilder().apply(builder)
return Location(lb.lat!!, lb.lng!!)
}
data class LocationBuilder(
var lat: Double? = null,
var lng: Double? = null
)
为了避免使用!!
操作员,我想编写一个合同,帮助编译器推断出一个智能广播,该智能广播说属性lat
和lng
不为空,但我无法成功地做到这一点。
我尝试过没有成功的事情,我相信这可能是因为我没有完全理解合同的动态。这些是风格:
fun LocationBuilder.buildSafely(dsl: LocationBuilder.()->Unit): LocationBuilder {
contract {
returnsNonNull() implies (this@buildSafely.lat != null && this@buildSafely.lng != null)
}
apply(dsl)
if(lat == null || lng == null) throw IllegalArgumentException("Invalid args")
return this
}
fun location(builder: LocationBuilder.()->Unit): Location {
val configuredBuilder = LocationBuilder().buildSafely(builder)
return Location(configuredBuilder.lat, configuredBuilder.lng)
/* I would expect a smart cast but I am getting a compile error stating that lat and lng may still be null */
}
所以问题是: