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