Kotlin 智能推斷
Koltin 中的智能推斷 類型 是一大特色(如同 C++ 中的 auto),可以自動幫我們推斷當前程式的類型
abstract class View
class EditView : View() {
fun input(s: String) {
println(s)
}
}
class Button : View() {
fun click() {
println("Button be click")
}
}
fun testView(view: View) {
when(view) {
// 不用強制轉型,直接可以使用!(方便 ~
is EditView -> view.input("TEST")
is Button -> view.click()
else -> throw IllegalArgumentException("Error")
}
}
fun main() {
testView(EditView())
testView(Button())
}
智能推斷的使用時機:標準庫
● 但 Kotlin 的智能推斷尚未完善,仍可能出現智能判斷失敗,導致編譯不通過的情況,如下狀況
String 已經透過 isNotNull
函數判斷 Not Null,不過下方在使用時仍須透過 ?.
or !!.
符號進行修正,才能正常編譯過
fun String?.isNotNull(): Boolean {
return this != null && this.isNotEmpty()
}
fun printlnLength(str : String? = null) {
if(str.isNotNull()) {
// 明明上面已經判斷過了
println(str.length) // Error
// println(str?.length) // Okay
// println(str!!.length) // Okay
}
}
同樣狀況,切換 Kotlin standard lib 中 String 的拓展函數 isNullOrEmpty
就不會有問題
fun printlnLength2(str : String? = null) {
if(!str.isNullOrEmpty()) {
println(str.length) // Okay
}
}
這其實是因為該函數內部使用了「contract
」,以下為 isNullOrEmpty
源碼
@kotlin.internal.InlineOnly
public inline fun CharSequence?.isNullOrEmpty(): Boolean {
contract {
returns(false) implies (this@isNullOrEmpty != null)
}
return this == null || this.length == 0
}
Kotlin Contact 規則、使用
通過契約,開發者可以向編譯器提供使用函數時的相關行為(也可以用來做類似保證的動作),幫助編譯器對程式分析
契約 Contact
的實現,就類似於 開發者和編譯器溝通的橋樑,編譯器必須無條件服從開法者訂下的條件
Contract 規則
● Contract 規則
A. 只能使用在頂層 top-level
函數,不能用在類中
B. contract 必須要在函數中的 首行
C. contract 後的所有行為都由開發者負責,這類似使用 !!.
符號
Contract 分類
● Contract 分類目前主要有兩種
A. Returns Contracts:向編譯器保證返回的是某個值,方便編譯器之後判斷是否需要提醒錯誤;一般有下面幾個形式
Returns Contracts | 說明 |
---|---|
returns (true) implies [返回時成立的條件] | implies 條件成立時返回 true |
returns (false) implies [返回時成立的條件] | implies 條件成立時返回 false |
returns (null) implies [返回時成立的條件] | implies 條件成立時返回 null |
returns() implies [返回時成立的條件] | implies 條件成立時正常返回 |
returnsNotNull() implies [返回時成立的條件] | implies 條件成立時返回非空數值 |
@kotlin.internal.InlineOnly
public inline fun <T : Any> requireNotNull(value: T?): T {
contract {
// 斷定 value 不為 null 就正常返回
returns() implies (value != null)
}
// 走到這一步,就確定 value 為 null
// 查看 requireNotNull 函數
return requireNotNull(value) { "Required value was null." }
}
public inline fun <T : Any> requireNotNull(value: T?, lazyMessage: () -> Any): T {
contract {
// 斷定 value 不為 null 就正常返回
returns() implies (value != null)
}
// 走到這一步,就確定 value 為 null
if (value == null) {
val message = lazyMessage()
throw IllegalArgumentException(message.toString())
} else {
return value
}
}
B. CallInPlace Contracts:在拓展函數 let
, apply
... 的源碼中會看見;其中的 callsInPlace
會通知編譯器,該函數在調用結束後,不會再被執行
InvocationKind 枚舉 | 說明 |
---|---|
AT_MOST_ONCE | 該函數只會被調用一次,或是根本不會調用! |
EXACTLY_ONCE | 該函數只會被調用一次 |
AT_LEAST_ONCE | 該函數至少被調用一次 |
UNKNOW | 該函數可被調用多次 |
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
// 走到這裡就保證,Lambda 函數只會被呼叫一次
block()
return this
}
更多的 Kotlin 語言相關文章
在這裡,我們提供了一系列豐富且深入的 Kotlin 語言相關文章,涵蓋了從基礎到進階的各個方面。讓我們一起來探索這些精彩內容!
Kotlin 語言基礎
● Kotlin 語言基礎:想要建立堅實的 Kotlin 基礎?以下這些文章將帶你深入探索 Kotlin 的關鍵基礎和概念,幫你打造更堅固的 Kotlin 語言基礎
Kotlin 特性、特點
● Kotlin 特性、特點:探索 Kotlin 的獨特特性和功能,加深對 Kotlin 語言的理解,並增強對於語言特性的應用
Kotlin 進階:協程、響應式、異步
● Kotlin 進階:協程、響應式、異步:若想深入學習 Kotlin 的進階主題,包括協程應用、Channel 使用、以及 Flow 的探索,請查看以下文章