Kotlin Contracts是kotlin 1.3推出的一个新特性,它主要作用是进一步提升kotlin编译器的智能转换(smartcasts)能力,先看看下面这个示例。
这样很符合逻辑,其实这背后是kotlin编译器帮我们做了智能转换,但是并不是所有的情况编译器都能这样默默的处理了,比如说,我们把判空处理放在另外一个独立的方法中。
仅仅是把功能封装成了一个单独的方法,之前的智能转换功能居然不生效了,这对于开发者来说很容易推断出s
可以转换为String类型而不是String?,但是对于编译器来说却比较麻烦,为了增强这类场景kotlin编译器的智能转换能力,所以推出了Contracts机制。
我们将以上代码判断字符串的部分改为kotlin标准库中的扩展方法isNullOrBlank
,则可以顺利编译通过。
下面是isNullOrBlank
方法的定义,从定义中我们可以看出它使用了Contracts机制。
后面是正常的判空处理,重点是contract这一段代码,它代表合约的内容:如果方法返回true,表明字符串实例不是null。编译器可以根据这个约定来决定是否可以将字符串s实例从String?类型转换为String类型。我们将上面提到编译出错的代码改动一下,使用Contracts机制来帮助编译器完成智能转换。
除了returns(value) implies(condition)
这种形式,还有以下几种。
returns() implies(condition)
,如果方法调用正常返回,则表明condition成立。returnsNotNull() implies(condition)
,如果方法返回值不为null,则表明condition成立。除了能够帮助编译器智能转换以外,Contracts机制还能帮助编译器在存在高阶函数时,判断一个变量是否初始化。先看看下面示例,因为编译器无法判断变量是否会初始化,所以导致编译出错。
从开发者角度来看,这个x = 42
这行代码会执行一次,也就是说x
会在println方法之前赋值,但是对于编译器来说,它却不能很智能的知道这个情况,所以就出现了编译错误。在ContractBuilder中还定义了方法callsInPlace,用于提示编译器传入高阶函数中的表达式的执行情况。
比如说上面的代码,如果我们使用Contracts机制提示编译器,block会被执行一次,那么它就能够知道x变量会在println方法之前被赋值,也就不会出现编译错误了。