本文由 Prefert 發表在 ScalaCool 團隊博客。編程
咱們在Dive Into Kotlin(二):Kotlin 類型結構設計中已經對Kotlin的類型系統進行過大體的介紹。bash
文中提到過: Any
類型是 Kotlin 中 全部非空類型(ex: String
, Int
) 的根類型。編程語言
當咱們須要和 Java 互操做的時候,Kotlin 把 Java 方法參數和返回類型中用到的 Object
類型看做 Any
(更確切地說是當作「平臺類型」)。當 Kotlin 函數中使用 Any
時,它會被編譯成 Java 字節碼中的 Object
。函數
什麼是平臺類型?ui
平臺類型本質上就是 Kotlin 不知道可空性信息的類型—全部 Java 引用類型在 Kotlin 中都表現爲平臺類型。當在 Kotlin 中處理平臺類型的值的時候,它既能夠被當作可空類型來處理,也能夠被當作非空類型來操做。spa
平臺類型的引入是 Kotlin 兼容 Java 時的一種權衡設計。試想下,若是全部來自 Java 的值都被當作非空,那麼就容易寫出比較危險的代碼。反之,若是 Java 值都強制當作可空,則會致使大量的
null
檢查。綜合考量,平臺類型是一種折中的設計方案。scala
在 Java 中,Object
類型位於其類型系統的頂級。若是說 Kotlin 與 Java 是100%兼容的,那咱們是否能夠說 Any 也是Kotlin的全部類型的頂級類型呢?在上一篇文章中,這個問題一樣困擾了我,官方也並無作出一個明確的說明。可是咱們能夠注意到的是, Kotlin 中引入了「可空類型」這個概念,這極可能會對系統層級結構產生影響。設計
在探索根類型以前,先讓咱們理清兩個概念:繼承(Inheriting
)和 子類型化(Subtyping
)。code
這是一個看似容易實則不簡單的問題:到底什麼纔是子類型化( Subtyping
)?咱們曾在Subtyping vs Typeclasses(一)這篇博客討論過這個問題。若是你只有 Java 這門編程語言的開發經驗,很容易陷入一個誤區——繼承關係決定父子類型關係。由於在 Java 中, 類與類型大部分狀況下都是「等價」的(在 Java 泛型出現前)。cdn
事實上,「繼承」和「子類型化」是兩個徹底不一樣的概念。
子類型化的核心是一種類型的替代關係(咱們也能夠稱之爲子類型多態),一般可表示爲:
S <: T
複製代碼
以上 S
是 T
的子類,這意味着在須要 T
類型值的地方,S
類型的值一樣適用,如在 Kotlin 中 Int
是 Number
的子類:
fun printNum(num: Number) {
println(num)
}
>>> val n: Int = 1
>>> printNum(n)
>>> 1
>>> printNum("I am a String")
error: type mismatch: inferred type is String but Number was expected
複製代碼
相對而言,繼承強調的是一種「實現上的複用」,而子類型化是一種類型語義的關係,與實現不要緊。在 Java 中,咱們彷佛也能夠經過類繼承來實現上述關係:
class S extends class T 複製代碼
因爲在聲明父子類型關係的同時,也聲明瞭繼承的關係,因此一般會形成了某種程度上的混淆,可是這並不能說明這兩個概念就是等價的。
雖然 Any
與 Any?
看起來沒有繼承關係,然而當咱們在須要用 Any?
類型值的地方,顯然能夠傳入一個類型爲 Any
的值,這在編譯上不會產生問題。反之卻行不通,好比:一個參數類型爲 Any
的函數,咱們傳入符合 Any?
類型的 null
值,就會出現以下的錯誤:
error: null can not be a value of a non-null type Any
複製代碼
以上,咱們也能夠初步得出結論:Any
的值能在全部狀況下代替 Any?
的值,這符合「子類型化」的概念。
所以,咱們能夠很大膽地說:在Kotlin的類型系統中,Any?
是 Any
的父類型,並且是全部類型的根類型,雖然當前的 Kotlin 官網文檔沒有介紹過這一點。
一個你可能會挑戰的問題是,若是 Any?
是 Any
的父類型,那麼 Any??
是否又是 Any?
的父類型, 若是成立,那麼是否意味着就沒有所謂的「全部類型的根類型」了?
其實,Kotlin 中的可空類型能夠看作所謂的 Union Type
,在程序中一般用 A | B
表示,近似於數學中的並集。若是用類型的並集來表示 Any?
,可寫爲 Any ∪ Null
。相應的 Any??
就表示爲 Any ∪ Null ∪ Null
,這等價於 Any ∪ Null
, 即 Any??
等價於 Any?
。所以,說 Any?
是全部類型的根類型是沒有問題的。