国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
跨越邊界: Java 模型以外的類(lèi)型策略

2006 年 6 月 12 日

當(dāng)談到 Java? 語(yǔ)言的類(lèi)型方法時(shí),Java 社區(qū)分為兩大陣營(yíng)。一些人喜歡編譯時(shí)錯(cuò)誤檢查,更好的安全性,以及改善的工具 —— 這些都是靜態(tài)類(lèi)型所能提供的特性。而另一些人則偏愛(ài)更動(dòng)態(tài)的類(lèi)型體驗(yàn)。這一次在 跨越邊界 中,您將看到兩種高生產(chǎn)力的非 Java 語(yǔ)言所使用的一些截然不同的類(lèi)型策略,并發(fā)現(xiàn)在 Java 編程中提高類(lèi)型靈活性的一些方法。

在對(duì)任何編程語(yǔ)言的討論中,爭(zhēng)議較大的一個(gè)問(wèn)題就是類(lèi)型模型。類(lèi)型決定可以使用哪些種類(lèi)的工具,并影響到應(yīng)用程序的設(shè)計(jì)。很多開(kāi)發(fā)人員將類(lèi)型與生產(chǎn)率或可維護(hù)性聯(lián)系起來(lái)(我就是其中的一個(gè))。典型的 Java 開(kāi)發(fā)人員通常都特別樂(lè)于維護(hù) Java 語(yǔ)言的類(lèi)型模型的地位,強(qiáng)調(diào) Java 語(yǔ)言可采用更好的開(kāi)發(fā)工具,在編譯時(shí)捕捉某些種類(lèi)的 bug(例如類(lèi)型不兼容和拼寫(xiě)錯(cuò)誤),以及性能等方面的優(yōu)勢(shì)。

如果您想理解一種新的編程語(yǔ)言,甚至一系列語(yǔ)言,那么通常應(yīng)該從類(lèi)型策略著手。在本文中,您將看到 Java 之外的一些語(yǔ)言中的類(lèi)型模型。我首先簡(jiǎn)要介紹任何語(yǔ)言設(shè)計(jì)者在類(lèi)型模型中必須考慮的一些決策,著重介紹靜態(tài)類(lèi)型和動(dòng)態(tài)類(lèi)型的一些不同的決策。我將展示一些不同極端的例子 —— Objective Caml 中的靜態(tài)類(lèi)型和 Ruby 中的動(dòng)態(tài)類(lèi)型。我還將談到 Java 語(yǔ)言的類(lèi)型限制,以及如何突破 Java 類(lèi)型的限制快速編程。

關(guān)于本系列

跨越邊界 系列中,作者 Bruce Tate 提出這樣一個(gè)觀點(diǎn):如今的 Java 程序員可通過(guò)學(xué)習(xí)其他方法和語(yǔ)言得到很好的其他思路。自從 Java 技術(shù)明顯成為所有開(kāi)發(fā)項(xiàng)目的最佳選擇以來(lái),編程前景已經(jīng)變化。其他的框架正影響構(gòu)建 Java 框架的方式,從其他語(yǔ)言學(xué)到的概念可以影響您的 Java 編程。您編寫(xiě)的 Python(或 Ruby、Smalltalk……)代碼可以改變您處理 Java 編碼的方式。

本系列為您介紹與 Java 開(kāi)發(fā)根本不同,但也可以直接應(yīng)用于 Java 開(kāi)發(fā)的編程概念和技術(shù)。在一些例子中,需要對(duì)技術(shù)進(jìn)行集成以利用它。在另外一些例子中,您將能夠直接應(yīng)用這些概念。單獨(dú)的工具不及其他語(yǔ)言和框架能夠影響 Java 社區(qū)中的開(kāi)發(fā)人員、框架甚至基本方法的思想那么重要。

類(lèi)型策略

至少可以從三個(gè)角度來(lái)看待類(lèi)型:

  • 靜態(tài)類(lèi)型還是動(dòng)態(tài)類(lèi)型,這取決于何時(shí) 實(shí)施類(lèi)型模型。靜態(tài)類(lèi)型語(yǔ)言在編譯時(shí)實(shí)施類(lèi)型。而動(dòng)態(tài)類(lèi)型語(yǔ)言通?;谝粋€(gè)對(duì)象的特征在運(yùn)行時(shí)實(shí)施類(lèi)型。

  • 強(qiáng)類(lèi)型還是弱類(lèi)型,這取決于如何 實(shí)施類(lèi)型模型。強(qiáng)類(lèi)型嚴(yán)格地實(shí)施類(lèi)型,如果發(fā)現(xiàn)有違反類(lèi)型規(guī)則的情況,則會(huì)拋出運(yùn)行時(shí)或編譯時(shí)錯(cuò)誤。而弱類(lèi)型則留有更多的余地。極端情況下,弱類(lèi)型語(yǔ)言(例如 Assembler)允許將任意數(shù)據(jù)類(lèi)型賦給另一種類(lèi)型(不管這種賦值是否有意義)。靜態(tài)類(lèi)型的語(yǔ)言既可以有強(qiáng)類(lèi)型,也可以有弱類(lèi)型;而動(dòng)態(tài)類(lèi)型系統(tǒng)通常是強(qiáng)類(lèi)型的,但也不完全是。

  • 顯式類(lèi)型還是隱式類(lèi)型,這取決于語(yǔ)言如何確定一個(gè)給定對(duì)象的類(lèi)型。顯式類(lèi)型語(yǔ)言要求聲明每個(gè)變量和每個(gè)函數(shù)參數(shù)。而隱式類(lèi)型語(yǔ)言則根據(jù)語(yǔ)言中的語(yǔ)法和結(jié)構(gòu)線索來(lái)確定對(duì)象的類(lèi)型。靜態(tài)類(lèi)型語(yǔ)言通常是顯式類(lèi)型的,但也不完全是;而動(dòng)態(tài)類(lèi)型語(yǔ)言幾乎都是隱式類(lèi)型的。

下面兩個(gè)例子很好地闡釋了其中兩個(gè)角度的內(nèi)涵。假設(shè)您編譯下面這段 Java 代碼:

class Test {                        public static void test(int i) {                        String s = i;                        }                        }                        

會(huì)收到如下錯(cuò)誤消息:

Test.java:3: incompatible types                        found   : int                        required: java.lang.String                        String s = i;                        ^                        1 error                        

執(zhí)行以下 Ruby 代碼:

1 + "hello"                        

會(huì)收到以下錯(cuò)誤消息:

TypeError: String can‘t be coerced into Fixnum                        from (irb):3:in ‘+‘                        from (irb):3                        

這兩種語(yǔ)言都傾向于強(qiáng)類(lèi)型,因?yàn)楫?dāng)您試圖使用一個(gè)它們期望之外的類(lèi)型結(jié)構(gòu)的對(duì)象時(shí),它們都會(huì)拋出錯(cuò)誤消息。Java 類(lèi)型策略在編譯時(shí)給出錯(cuò)誤消息,因?yàn)樗鼒?zhí)行靜態(tài)類(lèi)型檢查。而 Ruby 則是在運(yùn)行時(shí)給出錯(cuò)誤消息,因?yàn)?Ruby 支持動(dòng)態(tài)類(lèi)型。換句話說(shuō),Java 在編譯時(shí)將對(duì)象綁定到類(lèi)型。而 Ruby 則是在運(yùn)行時(shí)每當(dāng)更改對(duì)象的時(shí)候?qū)?duì)象綁定到類(lèi)型。由于我是在 Java 代碼中,而不是在 Ruby 中聲明變量的,因此可以看到 Java 語(yǔ)言的顯式類(lèi)型與 Ruby 的隱式類(lèi)型的工作方式不同。

在這三個(gè)角度中,靜態(tài)類(lèi)型與動(dòng)態(tài)類(lèi)型對(duì)于語(yǔ)言的特征有最大的影響,因此接下來(lái)我將重點(diǎn)解釋這兩種策略各自的優(yōu)點(diǎn)。

靜態(tài)類(lèi)型的優(yōu)點(diǎn)

在靜態(tài)類(lèi)型語(yǔ)言中,程序員(通過(guò)聲明或根據(jù)約定)或編譯器(根據(jù)結(jié)構(gòu)和語(yǔ)法線索)將一種類(lèi)型指定給一個(gè)變量,然后那個(gè)類(lèi)型就不會(huì)改變。靜態(tài)類(lèi)型通常需要額外的成本,因?yàn)殪o態(tài)類(lèi)型語(yǔ)言(例如 Java 語(yǔ)言)通常是顯式類(lèi)型的。這意味著必須聲明所有的變量,然后編譯代碼。成本也伴隨著收益:早期的錯(cuò)誤檢測(cè)。靜態(tài)類(lèi)型在最基層為編譯器提供多得多的信息。更多信息所帶來(lái)的好處就是,可以更早地捕捉到某些類(lèi)型的錯(cuò)誤,而動(dòng)態(tài)類(lèi)型語(yǔ)言只有到運(yùn)行時(shí)才能檢測(cè)到這些錯(cuò)誤。如果您一直等到運(yùn)行時(shí)才捕捉這些 bug,那么其中一些將進(jìn)入生產(chǎn)環(huán)境。也許這正是動(dòng)態(tài)類(lèi)型語(yǔ)言受到最多指責(zé)的一個(gè)方面。

另一種觀點(diǎn)則認(rèn)為現(xiàn)代軟件開(kāi)發(fā)團(tuán)隊(duì)通常會(huì)運(yùn)行自動(dòng)測(cè)試,動(dòng)態(tài)語(yǔ)言的支持者聲稱,即使是最簡(jiǎn)單的自動(dòng)測(cè)試也可以捕捉到大多數(shù)的類(lèi)型錯(cuò)誤。而動(dòng)態(tài)語(yǔ)言的支持者所能提供的對(duì)編譯時(shí)錯(cuò)誤檢測(cè)不利的最好論據(jù)是,早期檢測(cè)所帶來(lái)的好處相對(duì)于成本來(lái)說(shuō)是得不償失的,因?yàn)椴还苁欠袷褂脛?dòng)態(tài)類(lèi)型,最終都要進(jìn)行測(cè)試。

一種有趣的折中方法是在靜態(tài)類(lèi)型語(yǔ)言中使用隱式類(lèi)型,從而減少類(lèi)型的成本。開(kāi)放源代碼語(yǔ)言 Objective Caml (OCaml) 是靜態(tài)類(lèi)型語(yǔ)言 Lisp 的衍生物,它既能提供很好的性能,又不會(huì)犧牲生產(chǎn)率。OCaml 使用隱式類(lèi)型,因此可以編寫(xiě)下面這樣的采用靜態(tài)類(lèi)型的代碼:

# let x = 4+7                        

OCaml 返回:

val x : int = 11                        

根據(jù)表達(dá)式中的語(yǔ)法線索,OCaml 推斷出 x 的類(lèi)型。4int 型,7 也是 int 型,因此 x 也必定是 int 型。隱式類(lèi)型語(yǔ)言可以擁有 Java 語(yǔ)言所具有的所有類(lèi)型安全性,甚至更多。不同之處在于您需要提供的信息量,以及在閱讀程序時(shí)可用的信息量。很多喜歡靜態(tài)類(lèi)型的人更偏愛(ài)隱式類(lèi)型。他們寧愿讓編譯器來(lái)做這種事情,而不愿意被迫重復(fù)地在代碼中輸入變量的類(lèi)型。

隱式類(lèi)型系統(tǒng)一個(gè)較大的優(yōu)點(diǎn)是,不需要為函數(shù)的參數(shù)聲明類(lèi)型,因?yàn)榫幾g器會(huì)從傳入的值推斷出參數(shù)的類(lèi)型。因此同一個(gè)方法可以有多種用途。

關(guān)于重構(gòu)的謬誤

有些人認(rèn)為,要獲得具有重構(gòu)(refactoring)支持的良好 IDE,就必須具有靜態(tài)類(lèi)型特性,這種觀點(diǎn)是荒謬的。大多數(shù)現(xiàn)代 IDE 多少?gòu)脑缙诘?Smalltalk IDE 中吸收了一些東西。實(shí)際上,Eclipse 早期也有一些基本的東西是 Visual Age for Java 中的,而后者最初就是被發(fā)布在 Smalltalk 虛擬機(jī)上!Smalltalk Refactoring Browser 仍然是如今可用的功能最完善的重構(gòu)工具之一(見(jiàn)參考資料)。Java 語(yǔ)言仍然比大多數(shù)流行的動(dòng)態(tài)語(yǔ)言(除了 Smalltalk)具有更好的工具,靜態(tài)類(lèi)型是最大的原因。

并不是只有編譯器才能利用靜態(tài)類(lèi)型所提供的附加信息。IDE 可以通過(guò)靜態(tài)類(lèi)型為重構(gòu)提供更好的支持。幾年前,一種革命性的思想改變了開(kāi)發(fā)環(huán)境的工作方式。在 IDEA 和 Eclipse 中,您的代碼看上去像一個(gè)文本視圖,但是開(kāi)發(fā)環(huán)境實(shí)際上正在編輯 Abstract Syntax Tree (AST)。因此,當(dāng)需要重新命名一個(gè)方法或者類(lèi)的時(shí)候,開(kāi)發(fā)環(huán)境很容易通過(guò)在 AST 中精確定位找到方法或類(lèi)被引用的每個(gè)地方。如今,如果沒(méi)有通過(guò)靜態(tài)類(lèi)型簡(jiǎn)化的優(yōu)秀的重構(gòu),我們很難想像用 Java 語(yǔ)言編程。在我探索 Ruby 的時(shí)候,相對(duì)于其他任何工具或特性,我更懷念 IDEA。

靜態(tài)類(lèi)型還有其他一些優(yōu)點(diǎn),在這里我不會(huì)詳細(xì)描述。靜態(tài)類(lèi)型可以提供更好的安全性,而且顯然還可以提高代碼的可讀性。靜態(tài)類(lèi)型還可以提供更多的信息,使得編譯器更容易進(jìn)行優(yōu)化,從而提高性能。但是靜態(tài)類(lèi)型贏得開(kāi)發(fā)人員青睞的最大原因是更容易檢測(cè)錯(cuò)誤,而且有更多可用的工具。

動(dòng)態(tài)類(lèi)型的優(yōu)點(diǎn)

Ruby 專(zhuān)家 Dave Thomas 將動(dòng)態(tài)類(lèi)型稱作duck typing(見(jiàn)參考資料),這有兩層意思。第一層意思是說(shuō),這種語(yǔ)言不真正實(shí)現(xiàn)類(lèi)型 —— 它利用鴨子理論 解決這個(gè)問(wèn)題。第二層意思是說(shuō),如果什么東西走起來(lái)像鴨子,叫起來(lái)也像鴨子,那么它很可能就是一只鴨子。在編程語(yǔ)言的上下文中,duck typing 意味著如果一個(gè)對(duì)象對(duì)于某種類(lèi)型的方法有反應(yīng),那么事實(shí)上就可以把它看作那種類(lèi)型。這樣的特性可以導(dǎo)致一些有趣的優(yōu)化。

大多數(shù)偏愛(ài)動(dòng)態(tài)類(lèi)型的開(kāi)發(fā)人員除了強(qiáng)調(diào)早期錯(cuò)誤檢測(cè)會(huì)帶來(lái)不必要的成本外,還提到動(dòng)態(tài)類(lèi)型語(yǔ)言具有很好的可表達(dá)性和生產(chǎn)率。很簡(jiǎn)單,您通常可以用更少的關(guān)鍵詞表達(dá)更多的思想。作為一名新的 Ruby 擁護(hù)者,我深信動(dòng)態(tài)語(yǔ)言更能提高生產(chǎn)率,雖然我不能比常見(jiàn)的靜態(tài)語(yǔ)言的支持者拿出更多具體的證據(jù)來(lái)。但是,從我開(kāi)始編寫(xiě)更多的 Ruby 代碼起,我就感覺(jué)到自己的生產(chǎn)率有了明顯的提高。誠(chéng)然,我仍然會(huì)看到靜態(tài)類(lèi)型的優(yōu)點(diǎn),尤其是在工具集方面,但是我逐漸認(rèn)識(shí)到了靜態(tài)類(lèi)型的缺點(diǎn)。

當(dāng)我開(kāi)始用 Ruby 編寫(xiě)代碼時(shí),我受到的最大改變是產(chǎn)生和使用元編程結(jié)構(gòu)的能力。如果您從頭開(kāi)始一直關(guān)注跨越邊界 系列統(tǒng)的話,您就知道元編程,或者說(shuō)編寫(xiě)用于編寫(xiě)程序的程序,是 Ruby on Rails 的一大推動(dòng)力量,更一般地說(shuō),是特定于領(lǐng)域的語(yǔ)言的一大推動(dòng)力量。用 Ruby 編程時(shí),我通常會(huì)編寫(xiě)更大的構(gòu)建塊,或者用更大的塊進(jìn)行構(gòu)建。我發(fā)現(xiàn),與使用 Java 編程相比,我可以用更多類(lèi)型的可重用塊擴(kuò)展我的程序。就像在 Java 編程中,您可以用新的類(lèi)來(lái)擴(kuò)展程序。還可以添加方法和數(shù)據(jù)到已有的類(lèi)中,因?yàn)轭?lèi)是開(kāi)放式的。您可以使用 mix-in(后面 運(yùn)行時(shí)綁定 會(huì)講到)來(lái)添加核心功能到已有的類(lèi)中。還可以在任何時(shí)候根據(jù)需要改變一個(gè)對(duì)象的定義。我還是一名 Ruby 編程新手,這些功能用到的不多,但是當(dāng)我真正開(kāi)始使用它們時(shí),結(jié)果令人大吃一驚。

例如,為了添加一個(gè)攔截器,只需重新命名一個(gè)方法,并為原有的方法創(chuàng)建一個(gè)新的實(shí)現(xiàn)。為了攔截 new,可以編寫(xiě)以下代碼:

class Class                        alias_method :old_new, :new                        def new(*args)                        puts "Intercepted new" #do interception work here                        old_new(*args)                        end                        end                        

您不需要 AspectJ 庫(kù)、字節(jié)碼增強(qiáng)或一大堆的庫(kù)。您可以直接編寫(xiě)所需的攔截器。

動(dòng)態(tài)類(lèi)型在原始代碼行方面也可以節(jié)省精力。由于動(dòng)態(tài)語(yǔ)言幾乎都是類(lèi)型推斷式的,所以您不需要花多大力氣來(lái)表達(dá)基本思想。變量無(wú)需聲明即可直接使用。您也不必表達(dá)參數(shù)類(lèi)型的所有可能排列,只需輸入一組名稱。您的代碼可以更加具有多態(tài)性 —— 任何對(duì)一種類(lèi)型的方法有反應(yīng)的對(duì)象都可以看作這種類(lèi)型 —— 所以通常可以比其他語(yǔ)言更精簡(jiǎn)地表達(dá)思想。代碼中的耦合也可以變得更松散。當(dāng)您想改變某個(gè)東西的類(lèi)型時(shí),這種變化所波及的范圍很有限,所以不需要在更多的地方作出相應(yīng)的更改。

安全性還是靈活性

從某種意義上說(shuō),語(yǔ)言的靜態(tài)與動(dòng)態(tài)之爭(zhēng)的關(guān)鍵在于安全性與靈活性之間的取舍。靜態(tài)語(yǔ)言的支持者相信更安全的語(yǔ)言更好。而動(dòng)態(tài)語(yǔ)言的支持者卻不愿意為安全性付出任何代價(jià)。對(duì)于他們而言,對(duì)一種語(yǔ)言的衡量標(biāo)準(zhǔn)在于能多快地表達(dá)思想,目標(biāo)在于最大化程序員的效率。而另一方面,靜態(tài)語(yǔ)言專(zhuān)家則說(shuō),如果 在早期捕捉到 bug,那么就應(yīng)該 這么做,而且工具可以彌補(bǔ)語(yǔ)言中的限制。

生產(chǎn)率提高的最后一個(gè)原因是減少了編譯環(huán)節(jié)。很多動(dòng)態(tài)類(lèi)型語(yǔ)言是解釋性的,所以在編寫(xiě)程序后可以立即看到變化。即使沒(méi)有慣用的調(diào)試器,在 Ruby 中探索庫(kù)和應(yīng)用程序代碼的行為也更為容易,因?yàn)槟梢源蜷_(kāi)一個(gè)解釋器,通常可以直接在調(diào)試會(huì)話中打開(kāi)(我在 本系列的上一篇文章 中就展示了這一點(diǎn)),然后隨意探索。

但是……

然而,編譯不只是支持靜態(tài)類(lèi)型。靜態(tài)類(lèi)型的支持者還認(rèn)為可以獲得更好的性能。很多靜態(tài)語(yǔ)言,例如 Java 代碼、C 和 C++,都被稱作系統(tǒng)語(yǔ)言,因?yàn)樗鼈兪菢?gòu)建操作系統(tǒng)、設(shè)備驅(qū)動(dòng)程序和其他高性能系統(tǒng)代碼的最常用的語(yǔ)言。這又經(jīng)常導(dǎo)致動(dòng)態(tài)語(yǔ)言的支持者指責(zé)靜態(tài)語(yǔ)言總是太低級(jí),用它們來(lái)編寫(xiě)應(yīng)用程序生產(chǎn)率很低 —— 但那是一種很狹隘的觀點(diǎn)。OCaml 語(yǔ)言是一種很高級(jí)的語(yǔ)言,支持面向?qū)ο蟪绦蛟O(shè)計(jì)、函數(shù)式程序設(shè)計(jì)(如 Lisp 或 Erlang)或傳統(tǒng)的結(jié)構(gòu)化程序設(shè)計(jì)。其類(lèi)型模型是靜態(tài)的,很多人說(shuō)它的性能甚至比 C++ 的性能還好(參見(jiàn) 參考資料)。使用 OCaml 時(shí),靜態(tài)類(lèi)型導(dǎo)致的開(kāi)銷(xiāo)很小,因?yàn)檫@種語(yǔ)言是類(lèi)型推斷式的。雖然付出了這一點(diǎn)成本,但可以得到非常好的性能,編譯時(shí)類(lèi)型檢查,以及一個(gè)非常高級(jí)的語(yǔ)言。即使是 duck typing 最頑固的支持者也不得不承認(rèn)那些優(yōu)點(diǎn)。





回頁(yè)首


Java 語(yǔ)言中的類(lèi)型限制

Java 開(kāi)發(fā)人員充分利用靜態(tài)類(lèi)型。他們有最好的開(kāi)發(fā)工具,這些工具帶有代碼完成和重構(gòu)等功能,這些都傾向于靜態(tài)類(lèi)型?,F(xiàn)在開(kāi)始利用測(cè)試優(yōu)先開(kāi)發(fā)的很多 Java 程序員獲得了更大的穩(wěn)定性,因?yàn)榫幾g器可以捕捉與類(lèi)型相關(guān)的 bug。新的類(lèi)型特性,例如泛型,增強(qiáng)了類(lèi)型模型,并為編譯器提供更多的信息。但 Java 開(kāi)發(fā)人員常常對(duì)動(dòng)態(tài)類(lèi)型的優(yōu)點(diǎn)一無(wú)所知。

運(yùn)行時(shí)綁定

動(dòng)態(tài)類(lèi)型的靈活性比您想像的更重要。在某些方面,Java 開(kāi)發(fā)人員試圖通過(guò)使用更多的 XML(這樣可以推遲到運(yùn)行時(shí)進(jìn)行綁定)和字符串(這樣可以表示很多不同的類(lèi)型)來(lái)突破靜態(tài)類(lèi)型的限制。Ruby 中的配置通常采用 Ruby 代碼的形式,而 Java 編程中的配置通常采用 XML 的形式??紤] Spring 框架(參見(jiàn) 參考資料):為了配置一個(gè)一般的 Spring bean,您使用 XML。您必須提供一個(gè)有效的 Java 類(lèi)名,并為每個(gè)變量設(shè)置屬性。例如,持久引擎(如 Hibernate)需要一個(gè)會(huì)話工廠(參見(jiàn) 參考資料)。用 Java 語(yǔ)法配置一個(gè)數(shù)據(jù)訪問(wèn)對(duì)象很輕松:

  Dao myDataAccessObject = Dao.new(sessionFactory);                        

問(wèn)題是,這行代碼是在編譯時(shí)綁定的,這就太靜態(tài)了。為了測(cè)試,您常常需要用其他東西,例如一個(gè)模擬的數(shù)據(jù)訪問(wèn)對(duì)象來(lái)替換會(huì)話工廠或數(shù)據(jù)訪問(wèn)對(duì)象。所以,您不必像前面那樣硬編碼這個(gè)例子,而是使用一個(gè) Spring 之類(lèi)的框架,以 XML 來(lái)配置項(xiàng)目,如下所示(摘自名為 petclinic 的 Spring Framework 例子):

<bean id="myDao" class="org.springframework.samples.petclinic.hibernate.HibernateClinic">                        <property name="sessionFactory" ref="sessionFactory">                        </bean>                        

Spring 框架是目前 Java 社區(qū)中最重要、最有影響力的框架之一,因?yàn)樗鼓梢匝舆t綁定,并使系統(tǒng)主要元素之間的耦合性更為松散。而且,您不需要關(guān)心繼承就可以去耦。在 Java 編程中,尤其是在編寫(xiě)越來(lái)越多的 POJO(plain old Java object)的時(shí)候,使用繼承時(shí)必須特別小心,因?yàn)樵?Java 語(yǔ)言中只有一次這樣的機(jī)會(huì)。

在動(dòng)態(tài)語(yǔ)言,例如 Ruby 中,解決方案就截然不同。首先,我傾向于使用一個(gè) mix-in 來(lái)實(shí)現(xiàn)持久性。所有關(guān)聯(lián)只在 mix-in 中發(fā)現(xiàn)一次??梢园岩粋€(gè) mix-in 想像成一個(gè)接口,其背后有一個(gè)實(shí)現(xiàn)。換句話說(shuō),通過(guò) mix-in,可以添加多個(gè)功能到同一個(gè)對(duì)象中,而不必使用多重繼承。實(shí)際上,Active Record 通過(guò)繼承一個(gè)公共基類(lèi)來(lái)解決這個(gè)問(wèn)題,這個(gè)公共基類(lèi)混合了多種功能:

class Pojo < ActiveRecord::Base                        

在 Ruby 中,您不必關(guān)心繼承,因?yàn)槭褂瞄_(kāi)放的類(lèi)(允許動(dòng)態(tài)添加功能)和模塊(允許混入其他功能),您可以隨意添加更多的功能到對(duì)象中。那么緊密耦合呢?如果您想按 Java 的方式實(shí)現(xiàn)該類(lèi),那么可以看到:

class MyClass                        attr_accessor myDao   #defines getters and setters for myDao                        def initialize(session_factory)                        myDao = Dao.new(session_factory)                        end                        ...                        

initialize() 方法中的代碼看上去像一開(kāi)始的屬于禁忌的 Java 版本,因?yàn)樗诰幾g時(shí)將數(shù)據(jù)訪問(wèn)對(duì)象綁定到會(huì)話工廠。但這是一種動(dòng)態(tài)類(lèi)型語(yǔ)言,所以不必把自己關(guān)在一個(gè)小天地里。為了測(cè)試,總可以動(dòng)態(tài)地改變類(lèi)的定義。您可以在之后打開(kāi)已有的類(lèi):

class MyClass   #not redefining the class; just opening the existing class                        def myDao    #redefine the getter for myDao                        #do some work to generate the mock object                        return myMockObject                        end                        end                        





回頁(yè)首


結(jié)束語(yǔ)

從某種意義上講,作為某種編程語(yǔ)言的用戶,您就是那種語(yǔ)言的類(lèi)型策略的奴隸。而作為一名 Java 程序員,您應(yīng)該盡量用一種擁護(hù)類(lèi)型的方式編寫(xiě) Java 代碼。最大限度地利用類(lèi)型,并依靠社區(qū)來(lái)通過(guò)框架獲得更好的元編程支持,而不是自己進(jìn)行元編程,這些都是發(fā)揮自身優(yōu)勢(shì)的好方法。有很多 Java 框架都支持用于持久性(Hibernate 和 JDO)、事務(wù)(Spring 和 EJB)、模型-視圖-控制器(WebFlow 和 RIFE)以及編程模型(AspectJ)的元編程。

但是有時(shí)候需要放棄您所選擇的語(yǔ)言的類(lèi)型,不管您是在編寫(xiě)需要附加描述以獲得更好可讀性的代碼,還是試圖延遲類(lèi)型綁定,都可以這樣。Java 語(yǔ)言非常強(qiáng)大,您可以利用很多現(xiàn)成的項(xiàng)目:

  • Spring 框架使您可以將綁定推遲到運(yùn)行時(shí),并提供動(dòng)態(tài)類(lèi)型語(yǔ)言的很多功能。Spring 特別適合于添加功能到 POJO,運(yùn)行時(shí)配置,以及繞過(guò) Java 語(yǔ)言的類(lèi)型限制。

  • AspectJ 是面向方面編程模型在 Java 平臺(tái)上的一種實(shí)現(xiàn)(參見(jiàn) 參考資料)。AspectJ 使您可以引入橫切關(guān)注點(diǎn),而不必引入額外的語(yǔ)法,這種技術(shù)還使您可以克服 Java 語(yǔ)言的靜態(tài)特性。

  • Hibernate 項(xiàng)目和 Java Persistence API (JPA) 使您可以添加持久性到 POJO 中,同樣也不必改變底層的類(lèi)型。

  • XML 讓您可以同時(shí)表達(dá)數(shù)據(jù)和應(yīng)用程序配置。很多框架使用 XML 來(lái)克服 Java 語(yǔ)言的類(lèi)型限制。

您還有一個(gè)選擇。通過(guò)理解其他語(yǔ)言中的類(lèi)型策略,可以識(shí)別不適合 Java 策略的問(wèn)題。當(dāng)需要訪問(wèn) Java 平臺(tái) 而不是 Java 語(yǔ)言 時(shí),可以使用其他語(yǔ)言的 JVM 實(shí)現(xiàn)(參見(jiàn) 參考資料)。

在本系列的下一篇文章中,您將看到 Ruby on Rails 中的測(cè)試。您可以看到 Rails 與 Java 語(yǔ)言共有的一些思想,有些方面 Rails 占優(yōu),而在某些方面 Java 又具有明顯優(yōu)勢(shì)。到那時(shí),請(qǐng)繼續(xù)關(guān)注 “跨越邊界” 的后續(xù)文章。



參考資料

學(xué)習(xí)
  • 您可以參閱本文在 developerWorks 全球站點(diǎn)上的 英文原文

  • Beyond Java(O‘Reilly,2005 年):本文作者編寫(xiě)的一本書(shū),講述 Java 語(yǔ)言的優(yōu)缺點(diǎn)以及在某些方面可能對(duì) Java 平臺(tái)帶來(lái)挑戰(zhàn)的技術(shù)。

  • From Java To Ruby: Things Every Manager Should Know(Pragmatic Bookshelf,2006 年):本文作者編寫(xiě)的一本書(shū),講述何時(shí)何地從 Java 編程轉(zhuǎn)變到 Ruby on Rails,以及如何完成轉(zhuǎn)變。

  • Programming Ruby(Pragmatic Bookshelf,2005 年):一本流行的關(guān)于 Ruby 編程的書(shū)。

  • Duck typing:Dave Thomas 解釋他對(duì) Ruby 的類(lèi)型模型的定義。

  • Spring 框架:Spring 是一個(gè)很好的框架,可用于克服 Java 中靜態(tài)類(lèi)型的限制。

  • Hibernate:Hibernate 也許是最流行的用于 Java 的持久框架。

  • Spring 系列,第 2 部分: 當(dāng) Hibernate 遇上 Spring”(Naveen Balani,developerWorks,2005 年 8 月):將 Hibernate 事務(wù)與 Spring 面向方面編程相集成的指南。

  • AspectJ:AspectJ 項(xiàng)目受 Eclipse Foundation 的贊助。

  • Refactoring Browser:Martin Fowler‘s Refactoring 網(wǎng)站上的這個(gè)頁(yè)面談到了 Smalltalk Refactoring Browser 的一些優(yōu)點(diǎn)。

  • The rise of dynamic languages / programmer productivity”:數(shù)千篇討論動(dòng)態(tài)類(lèi)型語(yǔ)言和靜態(tài)類(lèi)型語(yǔ)言的生產(chǎn)率的文章之一。

  • Dynamic Productivity with Ruby: A Conversation with Yukihiro Matsumoto, Part II”:這篇對(duì) Ruby 創(chuàng)造者的訪談?dòng)懻摿嗽撜Z(yǔ)言的生產(chǎn)率。

  • Why Ocaml?”:這篇文章提供了關(guān)于 Ocaml 的性能特性的一些證據(jù)。

  • Java 技術(shù)專(zhuān)區(qū):這里可以找到數(shù)百篇關(guān)于 Java 編程各方面的文章。


獲得產(chǎn)品和技術(shù)
  • Objective Caml:OCaml 是組合了靜態(tài)類(lèi)型和隱式類(lèi)型的 Lisp 的衍生物,它在不犧牲生產(chǎn)率的情況下提供了高性能。

  • 用可從 developerWorks 直接下載的 IBM 試用軟件 構(gòu)建您的下一個(gè)開(kāi)發(fā)項(xiàng)目。


關(guān)于作者

Bruce Tate 居住在德克薩斯州的首府奧斯汀,他是一位父親,同時(shí)也是山地車(chē)手和皮艇手。他是三本 Java 暢銷(xiāo)書(shū)的作者,包括榮獲 Jolt 大獎(jiǎng)的 Better, Faster, Lighter Java。最近又出版了 Beyond Java 一書(shū)。他在 IBM 工作了 13 年,現(xiàn)在是 J2Life, LLC 的創(chuàng)始人兼顧問(wèn),在這里他潛心研究基于 Java 技術(shù)和 Ruby on Rails 的輕量級(jí)開(kāi)發(fā)策略和架構(gòu)。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Kotlin 與 Java有什么區(qū)別(最全最新的)
Ruby高手點(diǎn)評(píng)Scala編程語(yǔ)言十大絕招
InfoQ: 語(yǔ)言設(shè)計(jì)的藝術(shù)——讀《松本行弘的程序世界》
開(kāi)發(fā)者應(yīng)該了解的五種全新編程語(yǔ)言
在咖啡里加糖 論Java世界的Ruby
動(dòng)態(tài)語(yǔ)言和靜態(tài)語(yǔ)言的比較
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服