Scala的類型系統 比Java更靈活
原創51CTO編輯推薦:Scala編程語言專題
【51CTO獨家特稿】51CTO之前已經陸續發出了兩篇Scala之父Martin Odersky的訪談。在Artima方面,訪談仍在繼續,內容則逐漸向Scala語言的特性方面發展。如果您是Java程序員,或者C/C++程序員,對Scala這樣與Java極其類似但又有所改進的語言感興趣,那么推薦您閱讀以下文章:
Scala創始人:創造比Java更好的語言:“你總是不得不使用具有泛型類型的非泛型類型,即所謂的raw(原始)類型。還有,你不能改變數列行為,否則就會有未經檢查的警告。最重要的是,你不能利用數組做你想做的很多事情,比如生成一個具有類型參數的數組。后來在Scala,我們知道了實際上能如何實現這些事情……”
Java程序員,你為什么要關注Scala:“使用Scala我們最后所做的事是直接確定類的參數。你只需要在類名后寫一個參數列表,這些就成為類的參數。不存在獨立可變域和構造函數的概念,這些實際上轉變成了一些我們必須要解決的問題。”
下面繼續開始Martin Odersky的訪談之旅。今天,Martin Odersky將繼續講解Scala的特性,包括Scala的可擴展,以及類型的重要性。
Scala的可擴展性
Frank Sommers: 去年您在JavaOne大會的報告中,說Scala是一個“可擴展的語言”,可以隨意使用。這對于一個使用這種語言的程序員來說有什么幫助呢?(51CTO編者:這兩天正在舉行JavaOne 2009,以下是相關報道:6月2日外電頭條:JavaOne 2009 Sun最后的挽歌? 末代JavaOne大會看點解密 生存存疑)
Martin Odersky: 它給你帶來的幫助就是不再需要混用多種專門的語言。不論項目大小、應用領域是普通的還是特殊的,你都可以使用相同的語言。這意味著,你不必擔心如何從一個語言環境到另一個語言環境調用數據。
目前如果你想跨越環境調用數據,通常需要返回到低層次的描述。舉例來說,如你想要在Java中執行一個SQL查詢,并使用JDBC連接數據庫(51CTO編輯推薦:JDBC連接數據庫之十大技巧),查詢結果最終是一個字符串。這意味著程序中的一個小錯字將會導致運行時錯誤,很可能會體現在客戶端的網站上。沒有編譯器或類型系統能告訴你不應該出現那樣的錯誤。這是非常脆弱和危險的。因此,如果使用一種語言,就會避免類似問題。
另一個問題是工具。如果你使用的是一個單一的語言,你可以擁有一個單一的環境,帶有一些工具。但是,如果你使用許多不同的語言,你必須混合并匹配多種環境,你的工程構建會變得更加復雜和困難。
Frank Sommers: 您在上次的報告中還提到了可擴展性的概念,即Scala可以很容易擴展。你能否解釋一下如何擴展?其次,對程序員有怎樣的幫助?
Martin Odersky: 第一層面的可擴展性是從小到大,但我認為另外一個可擴展性的概念是指你的需求從一般擴展到特殊。你希望能夠把語言擴展到你所特別在意的領域。
比如數字(numeric)類型。現有許多特殊的數字類型,例如,針對破譯密碼人員的big整型,針對商務人士的big小數類型,針對科學家的復數類型,這樣的例子不勝枚舉。每一個領域的人都深切關注數據類型,但包含所有類型的語言將會是難以駕馭的。
答案當然是說,好吧,讓我們做一個包含這些類型的類庫。但是,如果你真的關心這個應用程序的領域,你希望代碼在訪問這些類時能夠像訪問內置類型那樣整潔圓潤。于是你想要這樣的擴展機制,可以讓你編寫這樣的類庫,使得類庫的使用者甚至感覺不到它是個類庫。對于一個類庫的使用者,假設一個big小數類庫, 使用BigDecimal類型應該像使用內置Int類型那樣方便。
#p#
小型程序中的類型
Frank Sommers: 您剛才提到了在一種語言(而非多種語言)背景下類型的重要性。我想大多數人在編寫大型程序時都會贊賞類型的有用性。當你在編寫大規模程序時,類型可以幫助你組織程序,可以讓程序修改具有可靠性。但是,如果我們編寫小型程序,類型會起到什么幫助,例如只編寫一個腳本程序?類型還同樣那么重要嗎?
Martin Odersky: 可能在編寫小型程序時,類型的重要性會降低。類型有時候讓人覺得有很多細小的地方很繁瑣。通常讓人厭煩的部分是類型的定義,這很多余,需要手工鍵入很多字符。當然,有用的部分是,類型可以幫你提示錯誤,可以給你提供有用的程序文檔,可以為安全重構提供一張安全網。
Scala擁有類型推理功能,試圖讓你盡量減少鍵入煩人的字符。這意味著如果你編寫一個腳本,你可以不寫任何類型。因為你可以不必考慮,系統會為你推斷。與此同時,類型就已經存在了,如果你的腳本中有類型錯誤,編譯器會捕獲錯誤并返回給你一個錯誤信息。我相信,無論是腳本還是一個大型系統,通過編譯器迅速解決這個問題總是比以后再處理要方便。
你仍然需要單元測試來測試程序邏輯,但相對于動態類型語言,你不再需要大量瑣碎的單元測試,如以往的類型測試。根據很多人的經驗,單元測試數量遠遠小于動態語言。項目開發周期數會隨之減少,這是我們的一些實例經驗。
其他一些反對靜態類型系統的人認為,它對你想表達的事情有太多限制。人們說,“我想自由地表達自己,我不想要靜態類型系統來妨礙我。”根據我使用Scala的經驗,我認為這是不正確的,原因有兩個。首先,Scala的類型系統實際上是非常靈活的,所以它通常可以讓你以一個非常靈活的方式編寫代碼,但是像Java的類型系統就不太靈活,使用起來就比較困難。其次是帶有模式匹配,你可以以一個非常靈活的方式恢復類型信息。
模式匹配的思想是,在Scala中我可以獲得一個對此一無所知的對象,然后通過一次構造,例如一個switch語句,為其針對一些模式進行匹配。如果它屬于其中一個模式,還可以立即取出值域融入到本地變量。模式匹配是一個內置入Scala的構造方法。很多Scala程序都使用它。這是Scala處理事情的一個常規方式。有趣的是,通過做模式匹配你還可以自動恢復類型。你提交一個對象,對此對象你一無所知。如果有一個模式匹配成功,實際上,你就知道你擁有適合某個類型模式的代碼。系統可以使用它。
由于模式匹配,你可以很容易擁有一個類型普通的系統,甚至最普通的情況類似于每個變量都是Object類型,但你仍然可以通過使用模式匹配得到所有想要得到的類型。所以在這個意義上,你可以使用Scala更好地編程,就仿佛是使用一個動態類型語言一樣。您可以到處都使用Object類型,然后隨處進行模式匹配。現在,人們通常不這樣做,因為想要更多地利用靜態類型的優點。相比之下,Java中的Analog,你不得不使用大量的類型測試(instanceof)。我完全理解人們為什么反對在所有地方都這樣做。
Duck Typing(鴨子類型)
Bill Venners: 我觀察到的Scala的其中一件事是,與Java類型系統相比,在Scala的類型系統中,我可以表達更多的關于程序的事情。覺得Java是一個動態語言的人往往解釋說,他們對類型系統感到很沮喪,并發現如果他們擺脫靜態類型,就會有更好的體驗。然而似乎Scala答案是,試圖讓類型系統更好,改善它,讓它更有用,使用起來更方便。那么,什么事情是在Scala類型系統中可以做到,而在Java類型系統中卻做不到的?
Duck Typing 是一種動態類型的概念,對象的類型由其運行時支持的屬性和方法決定。
Martin Odersky: 反對Java類型系統的理由之一是,它不含有duck typing。duck typing的解釋為,如果一只動物,走起來像鴨子,叫起來像鴨子,就可以把它當作鴨子。翻譯過來就是,如果它含有我想要的功能,那么我可以把它當作真的來對待。舉例來說,我想要一個可關閉的資源。我想說,“需要有一個close方法。”我不關心它是一個File或Channel或其他任何對象。
在Java中,為了完成這個工作,你需要一個包含方法的公共接口,每個人都必須實現該接口。首先,這導致了大量的接口和許多樣板代碼。其次,如果在既成事實之后再考慮這個接口是不可能的。如果你先寫了這個類,那么這個類就是已經存在的,你就不可以在不破壞源代碼的情況下再添加新接口,除非你控制所有客戶端。因此,你就受到了類型強加給你的這些限制。
Scala比Java更富表現力的一個方面是,它可以讓你表達上述事情。在Scala中,可以有這樣一個類型說明:帶有close方法的任何對象,close方法不含參數并返回Unit(相當于Java的void)。你還可以結合其他方面的限制。你可以說:繼承于某一特定類的任何類,具有某些帶有簽名的特殊方法。或者你可以說:繼承于這個類的任何類,并含有一個特定類型的內部類。從本質上講,你可以通過說明類型需求在結構上刻畫類型,以便使用它們。
原文:The Purpose of Scala's Type System(Martin Odersky訪談錄)
您正在閱讀的是:Scala的類型系統 比Java更靈活
【相關閱讀】
























