可檢驗(yàn)屬性。靜態(tài)類型系統(tǒng)可以保證消除某些運(yùn)行時(shí)的錯(cuò)誤。例如可以保證:布爾型不會(huì)與
整數(shù)型相加;私有變量不會(huì)從類的外部被訪問;用正確數(shù)量的參數(shù)調(diào)用了函數(shù);字符串集只能加入
字符串。
不過當(dāng)前的靜態(tài)類型系統(tǒng)還不能查到其他類型的錯(cuò)誤。比方說,通常查不到無法終結(jié)的函數(shù),數(shù)組
越界,或除零錯(cuò)誤。同樣也查不到你的程序不符合規(guī)格說明書(假設(shè)有這么一份規(guī)格說明書)。因
此有些人認(rèn)為靜態(tài)類型系統(tǒng)不太有用而忽視它。批評(píng)說既然這種類型系統(tǒng)只能發(fā)現(xiàn)簡單錯(cuò)誤,而單
元測試能提供更廣泛的覆蓋,那又為何自尋煩惱使用靜態(tài)類型呢?我們認(rèn)為這種說法不正確。盡管
靜態(tài)類型系統(tǒng)確實(shí)不能替代單元測試,但是卻能減少用來測試這些屬性的單元測試的數(shù)量。同樣,
單元測試也不能替代靜態(tài)類型。總而言之,如Edsger Dijkstra 所說,測試只能證明存在錯(cuò)誤,而非
不存在。14因此,靜態(tài)類型能給的保證或許很簡單,但這些保證無論多少測試都給不了。
安全的重構(gòu)。靜態(tài)類型系統(tǒng)提供了讓你具有高度信心去變動(dòng)代碼基礎(chǔ)的安全網(wǎng)。試想一個(gè)給
方法新增參數(shù)的重構(gòu)實(shí)例。在靜態(tài)類型語言中,你可以完成修改,重編譯你的系統(tǒng)并簡單地修改所
有引起類型錯(cuò)誤的代碼行。一旦完成了這些,你可以確信已經(jīng)發(fā)現(xiàn)了所有需要修改的地方。這種信
心對(duì)于其他的簡單重構(gòu),如改變方法名或把方法從一個(gè)類移到另一個(gè),都會(huì)有效。靜態(tài)類型檢查會(huì)
在所有的例子中提供足夠的確信,表明新系統(tǒng)和舊系統(tǒng)可以一樣的工作。
文檔。靜態(tài)類型是被編譯器檢查過正確性的程序文檔。不像普通的注釋,類型標(biāo)注永遠(yuǎn)都不
會(huì)過期(至少如果包含它的源文件近期剛剛通過編譯就不會(huì))。更進(jìn)一步說,編譯器和集成開發(fā)環(huán)
境可以利用類型標(biāo)注提供更好的上下文幫助。舉例來說,集成開發(fā)環(huán)境可以通過判定選中表達(dá)式的
靜態(tài)類型,找到類型的所有成員,并全部顯示出來。
def f(x: String) = ...
知道f 的變量應(yīng)該是String 是有用的。另一方面,以下例子中兩個(gè)標(biāo)注至少有一個(gè)是討厭的:
val x: HashMap[Int, String] = new HashMap[Int, String]()
很明顯,x 是以Int 為鍵,String 為值的HashMap 這句話說一遍就夠了;同樣的句子沒必要重
復(fù)兩遍。
Scala 有非常精于此道的類型推斷系統(tǒng),能讓你省略幾乎所有的通常被認(rèn)為是討厭的類型信息。前面
的例子可以改寫成以下兩種方式:
val x = new HashMap[Int, String]()
val x: Map[Int, String] = new HashMap()
Scala 里的類型推斷不止于此。實(shí)際上,就算用戶代碼絲毫沒有顯式類型也不稀奇。因此,Scala 程
序經(jīng)常看上去有點(diǎn)像是動(dòng)態(tài)類型腳本語言寫出來的程序。尤其在客戶應(yīng)用代碼中作為預(yù)編譯代碼庫
控件的膠水代碼時(shí),表現(xiàn)得更為顯著。而對(duì)于庫控件來說不是這么回事,因?yàn)樗鼈兂3S玫较喈?dāng)精
妙的類型去使其適于靈活使用的模式。這是由代碼的實(shí)際情況決定的。畢竟,構(gòu)成可重用控件接口
的成員的類型符號(hào)應(yīng)該是顯式給出的,因?yàn)樗鼈儤?gòu)成了控件和它的使用者間契約的重要部分。