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