Scala 編譯器通常可以推論表達式的類型,因此您不必明確宣告它。
省略類型
val businessName = "Montreux Jazz Café"
編譯器可以偵測 businessName
是字串。它在方法中運作方式類似
def squareOf(x: Int) = x * x
編譯器可以推論回傳類型是 Int
,因此不需要明確的回傳類型。
對於遞迴方法,編譯器無法推論結果類型。以下是會因此而導致編譯器失敗的程式
def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1)
def fac(n: Int) = if n == 0 then 1 else n * fac(n - 1)
呼叫 多型方法 或實例化 泛型類別 時,指定類型參數也不是強制性的。Scala 編譯器會從內容和實際方法/建構函數參數的類型推論出這些遺失的類型參數。
以下是兩個範例
case class MyPair[A, B](x: A, y: B)
val p = MyPair(1, "scala") // type: MyPair[Int, String]
def id[T](x: T) = x
val q = id(1) // type: Int
編譯器使用 MyPair
的引數類型來找出 A
和 B
的類型。對 x
的類型也是如此。
參數
編譯器從不推論方法參數類型。但是,在某些情況下,當函式作為引數傳遞時,它可以推論匿名函式參數類型。
Seq(1, 3, 4).map(x => x * 2) // List(2, 6, 8)
映射的參數為 f: A => B
。由於我們將整數放入 Seq
,編譯器知道 A
是 Int
(即 x
是整數)。因此,編譯器可以從 x * 2
推斷出 B
的類型為 Int
。
何時不依賴類型推論
一般來說,宣告公開 API 中公開的成員類型較為容易閱讀。因此,我們建議您為將公開給您的程式碼使用者的任何 API 明確指定類型。
此外,類型推論有時會推論出過於具體的類型。假設我們撰寫
var obj = null
然後我們無法繼續進行此重新指派
obj = new AnyRef
它不會編譯,因為推論出的 obj
類型為 Null
。由於該類型的唯一值為 null
,因此無法指派不同的值。