scala : 類型與類

scala類型系統:1) 類型與類

在Java裏,一直到jdk1.5以前,咱們說一個對象的類型(type),都與它的class是一一映射的,經過獲取它們的class對象,好比 String.classint.classobj.getClass() 等,就能夠判斷它們的類型(type)是否是一致的。java

而到了jdk1.5以後,由於引入了泛型的概念,類型系統變得複雜了,而且由於jvm選擇了在運行時採用類型擦拭的作法(兼容性考慮),類型已經不能單純的用class來區分了,好比 List<String> 和List<Integer> 的class 都是 Class<List>,然而二者類型(type)倒是不一樣的。泛型類型的信息要經過反射的技巧來獲取,同時java裏增長了Type接口來表達更泛的類型,這樣對於 List<String>這樣由類型構造器類型參數組成的類型,能夠經過 Type 來描述;它和 List<Integer> 類型的對應的Type對象是徹底不一樣的。es6

在Scala裏,類型系統又比java複雜不少,泛型從一開始就存在,還支持高階的概念(後續會講述)。因此它沒有直接用Java裏的Type接口,而是本身提供了一個scala.reflect.runtime.universe.Type (2.10後)編程

在scala裏獲取類型信息是比較便捷的:jvm

scala> import scala.reflect.runtime.universe._

scala> class A

scala> typeOf[A]
res44: reflect.runtime.universe.Type = A

一樣scala裏獲取類(Class)信息也很便捷,相似:編程語言

scala> classOf[A]
res52: Class[A] = class A

另外,由於java的Object裏提供了getClass方法,對於對象來講,能夠直接調用這個方法es5

scala> val a = new A

scala> a.getClass
res53: Class[_ <: A] = class A


scala> trait T

scala> classOf[T]
res50: Class[T] = interface T

scala> typeOf[T]
res51: reflect.runtime.universe.Type = T

注意,typeOf 和 classOf 方法接收的都是類型符號(symbol),並非對象實例spa

scala> object O

scala> classOf[O] // 這裏O是一個單例對象
<console>:14: error: not found: type O

對於實例,要獲取他的 Class 信息,只有經過 getClass 方法scala

scala> O.getClass
res60: Class[_ <: O.type] = class O$

注意到了,上面的 單例對象O 對應的class是 O$ 而不是 O,你經過 :javap O 也能看到這個單例反編譯後是一個名爲O$的java classcode

而這個單例的類型更有趣了:O.type 看上去像是這個單例內部的一個成員,用這個成員的值表示其類型;實際上.type以前的均可以看作是一種類型路徑,這種特殊的類型也叫單例類型,它是面向對象實例的,每一個實例均可以經過.type方式表達它的單例類型,這個後續咱們再說。對象

再舉一個例子:

scala> class A { class B }  // 嵌套類

scala> val a1 = new A
scala> val a2 = new A

scala> val b1 = new a1.B
scala> val b2 = new a2.B

對於內部類B的實例,它們的class都是相同的: A$B

scala> b1.getClass
res8: Class[_ <: a1.B] = class A$B

scala> b1.getClass == b2.getClass
res7: Boolean = true

而它們的類型倒是不一樣的:

scala> typeOf[a1.B] == typeOf[a2.B]
res10: Boolean = false

這是由於內部類型依賴外部實例(路徑依賴類型),外部實例不一樣,它們也不一樣。但還能夠對這種類型再抽象

scala> typeOf[a1.B] <:< typeOf[A#B]
res11: Boolean = true

scala> typeOf[a2.B] <:< typeOf[A#B]
res12: Boolean = true

這裏A#B涉及到類型投影的概念,之後再講。

簡單的說,類(class)與類型(type)是兩個不同的概念(在java裏由於早期一直使用class表達type,而且如今也延續這樣的習慣);類型(type)比類(class)更」具體」,任何數據都有類型。類是面向對象系統裏對同一類數據的抽象,在沒有泛型以前,類型系統不存在高階概念,直接與類一一映射,而泛型出現以後,就不在一一映射了。好比定義class List[T] {}, 能夠有List[Int] 和 List[String]等具體類型,它們的類是同一個List,但類型則根據不一樣的構造參數類型而不一樣。

類型一致的對象它們的類也是一致的,反過來,類一致的,其類型不必定一致。

scala> classOf[List[Int]] == classOf[List[String]]
res16: Boolean = true

scala> typeOf[List[Int]] == typeOf[List[String]]
res17: Boolean = false

在jvm裏,類的實例數據都是引用形式,而類型沒有這個約束,基礎類型int,byte,char等就是非引用的。(雖然能夠經過int.class來獲取Class對象,但並不能找到有定義class int的地方,這只是早期java爲了統一用class來承載其類型信息的方式)

小結,類型是全部編程語言都有的概念,一切數據都有類型。類更多存在於面嚮對象語言,非面嚮對象語言也有「結構體」等與之類似的概念;類是對數據的抽象,而類型則是對數據的」分類」,類型比類更「具體」,更「細」一些。

相關文章
相關標籤/搜索