<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 0,  comments - 17,  trackbacks - 0
    abstract class和interface是Java語言中對于抽象類定義進(jìn)行支持的兩種機(jī)制,正 是由于這兩種機(jī)制的存在,才賦予了Java強(qiáng)大的面向?qū)ο竽芰Αbstract class和interface之間在對于抽象類定義的支持方面具有很大的相似性,甚至可以相互替換,因此很多開發(fā)者在進(jìn)行抽象類定義時(shí)對于 abstract class和interface的選擇顯得比較隨意。其實(shí),兩者之間還是有很大的區(qū)別的,對于它們的選擇甚至反映出對于問題領(lǐng)域本質(zhì)的理解、對于設(shè)計(jì)意圖 的理解是否正確、合理。本文將對它們之間的區(qū)別進(jìn)行一番剖析,試圖給開發(fā)者提供一個(gè)在二者之間進(jìn)行選擇的依據(jù)。

    理解抽象類


    abstract class和interface在Java語言中都是用來進(jìn)行抽象類(本文中的抽象類并非從abstract class翻譯而來,它表示的是一個(gè)抽象體,而abstract class為Java語言中用于定義抽象類的一種方法,請讀者注意區(qū)分)定義的,那么什么是抽象類,使用抽象類能為我們帶來什么好處呢?


    在 面向?qū)ο蟮母拍钪校覀冎浪械膶ο蠖际峭ㄟ^類來描繪的,但是反過來卻不是這樣。并不是所有的類都是用來描繪對象的,如果一個(gè)類中沒有包含足夠的信息來 描繪一個(gè)具體的對象,這樣的類就是抽象類。抽象類往往用來表征我們在對問題領(lǐng)域進(jìn)行分析、設(shè)計(jì)中得出的抽象概念,是對一系列看上去不同,但是本質(zhì)上相同的 具體概念的抽象。比如:如果我們進(jìn)行一個(gè)圖形編輯軟件的開發(fā),就會發(fā)現(xiàn)問題領(lǐng)域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它們又都屬于形狀這 樣一個(gè)概念,形狀這個(gè)概念在問題領(lǐng)域是不存在的,它就是一個(gè)抽象概念。正是因?yàn)槌橄蟮母拍钤趩栴}領(lǐng)域沒有對應(yīng)的具體概念,所以用以表征抽象概念的抽象類是 不能夠?qū)嵗摹?/font>


    在 面向?qū)ο箢I(lǐng)域,抽象類主要用來進(jìn)行類型隱藏。我們可以構(gòu)造出一個(gè)固定的一組行為的抽象描述,但是這組行為卻能夠有任意個(gè)可能的具體實(shí)現(xiàn)方式。這個(gè)抽象描述 就是抽象類,而這一組任意個(gè)可能的具體實(shí)現(xiàn)則表現(xiàn)為所有可能的派生類。模塊可以操作一個(gè)抽象體。由于模塊依賴于一個(gè)固定的抽象體,因此它可以是不允許修改 的;同時(shí),通過從這個(gè)抽象體派生,也可擴(kuò)展此模塊的行為功能。熟悉OCP的讀者一定知道,為了能夠?qū)崿F(xiàn)面向?qū)ο笤O(shè)計(jì)的一個(gè)最核心的原則OCP(Open- Closed Principle),抽象類是其中的關(guān)鍵所在。


    OCP(Open-Closed Principle)
    意 思是,在一個(gè)系統(tǒng)中,對于擴(kuò)展是開放的,對于修改是關(guān)閉的,一個(gè)好的系統(tǒng)是在不修改源代碼的情況下,可以擴(kuò)展你的功能..而實(shí)現(xiàn)開閉原則的關(guān)鍵就是抽象 化.   在"開-閉"原則中,不允許修改的是抽象的類或者接口,允許擴(kuò)展的是具體的實(shí)現(xiàn)類,抽象類和接口在"開-閉"原則中扮演著極其重要的角色,即要預(yù)知可能變 化的需求,又預(yù)見所有可能已知的擴(kuò)展,所以在這里"抽象化"是關(guān)鍵!!!
    從語法定義層面看abstract class和interface

    在語法層面,Java語言對于abstract class和interface給出了不同的定義方式,下面以定義一個(gè)名為Demo的抽象類為例來說明這種不同。

    使用abstract class的方式定義Demo抽象類的方式如下:


    abstract class Demo {

    abstract void method1();
    abstract void method2();



    使用interface的方式定義Demo抽象類的方式如下:


    interface Demo {
    void method1();
    void method2();

    }

    在abstract class方式中,Demo可以有自己的數(shù)據(jù)成員,也可以有非abstarct的成員方法,而在interface方式的實(shí)現(xiàn)中,Demo只能夠有靜態(tài)的 不能被修改的數(shù)據(jù)成員(也就是必須是static final的,不過在interface中一般不定義數(shù)據(jù)成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊 形式的abstract class。


        從編程的角度來看,abstract class和interface都可以用來實(shí)現(xiàn)"design by contract "
    (DBC,契約式設(shè)計(jì))的思想。但是在具體的使用上面還是有一些區(qū)別的。

    首先,abstract class在Java語言中表示的是一種繼承關(guān)系,一個(gè)類只能使用一次繼承關(guān)系。但是,一個(gè)類卻可以實(shí)現(xiàn)多個(gè)interface。也許,這是Java語言的設(shè)計(jì)者在考慮Java對于多重繼承的支持方面的一種折中考慮吧。


    其次,在abstract class的定義中,我們可以賦予方法的默認(rèn)行為。但是在interface的定義中,方法卻不能擁有默認(rèn)行為,為了繞過這個(gè)限制,必須使用委托,但是這會 增加一些復(fù)雜性,有時(shí)會造成很大的麻煩。


    在 抽象類中不能定義默認(rèn)行為還存在另一個(gè)比較嚴(yán)重的問題,那就是可能會造成維護(hù)上的麻煩。因?yàn)槿绻髞硐胄薷念惖慕缑妫ㄒ话阃ㄟ^abstract class或者interface來表示)以適應(yīng)新的情況(比如,添加新的方法或者給已用的方法中添加新的參數(shù))時(shí),就會非常的麻煩,可能要花費(fèi)很多的時(shí) 間(對于派生類很多的情況,尤為如此)。但是如果界面是通過abstract class來實(shí)現(xiàn)的,那么可能就只需要修改定義在abstract class中的默認(rèn)行為就可以了。


    同 樣,如果不能在抽象類中定義默認(rèn)行為,就會導(dǎo)致同樣的方法實(shí)現(xiàn)出現(xiàn)在該抽象類的每一個(gè)派生類中,違反了"one rule,one place"原則,造成代碼重復(fù),同樣不利于以后的維護(hù)。因此,在abstract class和interface間進(jìn)行選擇時(shí)要非常的小心。
    從設(shè)計(jì)理念層面看abstract class和interface

    上 面主要從語法定義和編程的角度論述了abstract class和interface的區(qū)別,這些層面的區(qū)別是比較低層次的、非本質(zhì)的。本小節(jié)將從另一個(gè)層面:abstract class和interface所反映出的設(shè)計(jì)理念,來分析一下二者的區(qū)別。作者認(rèn)為,從這個(gè)層面進(jìn)行分析才能理解二者概念的本質(zhì)所在。

    前 面已經(jīng)提到過,abstarct class在Java語言中體現(xiàn)了一種繼承關(guān)系,要想使得繼承關(guān)系合理,父類和派生類之間必須存在"is a"關(guān)系,即父類和派生類在概念本質(zhì)上應(yīng)該是相同的(參考文獻(xiàn)〔3〕中有關(guān)于"is a"關(guān)系的大篇幅深入的論述,有興趣的讀者可以參考)。對于interface 來說則不然,并不要求interface的實(shí)現(xiàn)者和interface定義在概念本質(zhì)上是一致的,僅僅是實(shí)現(xiàn)了interface定義的契約而已。為了使 論述便于理解,下面將通過一個(gè)簡單的實(shí)例進(jìn)行說明。


    考慮這樣一個(gè)例子,假設(shè)在我們的問題領(lǐng)域中有一個(gè)關(guān)于Door的抽象概念,該Door具有執(zhí)行兩個(gè)動作open和close,此時(shí)我們可以通過abstract class或者interface來定義一個(gè)表示該抽象概念的類型,定義方式分別如下所示:


    使用abstract class方式定義Door:


    abstract class Door {
    abstract void open();
    abstract void close();

    }

     
    使用interface方式定義Door:



    interface Door {
    void open();
    void close();
    }

     
    其他具體的Door類型可以extends使用abstract class方式定義的Door或者implements使用interface方式定義的Door。看起來好像使用abstract class和interface沒有大的區(qū)別。


    如 果現(xiàn)在要求Door還要具有報(bào)警的功能。我們該如何設(shè)計(jì)針對該例子的類結(jié)構(gòu)呢(在本例中,主要是為了展示abstract class和interface反映在設(shè)計(jì)理念上的區(qū)別,其他方面無關(guān)的問題都做了簡化或者忽略)。下面將羅列出可能的解決方案,并從設(shè)計(jì)理念層面對這些 不同的方案進(jìn)行分析。


    解決方案一:


    簡單的在Door的定義中增加一個(gè)alarm方法,如下:


    abstract class Door {
    abstract void open();
    abstract void close();

    abstract void alarm();
    }

     
    或者


    interface Door {
    void open();
    void close();
    void alarm();
    }

     
    那么具有報(bào)警功能的AlarmDoor的定義方式如下:


    class AlarmDoor extends Door {
    void open() { … }
    void close() { … }
    void alarm() { … }
    }

     
    或者


    class AlarmDoor implements Door {

    void open() { … }
    void close() { … }
    void alarm() { … }


    這 種方法違反了面向?qū)ο笤O(shè)計(jì)中的一個(gè)核心原則ISP(Interface Segregation Priciple),在Door的定義中把Door概念本身固有的行為方法和另外一個(gè)概念"報(bào)警器"的行為方法混在了一起。這樣引起的一個(gè)問題是那些僅僅 依賴于Door這個(gè)概念的模塊會因?yàn)?報(bào)警器"這個(gè)概念的改變(比如:修改alarm方法的參數(shù))而改變,反之依然。


    解決方案二:


    既 然open、close和alarm屬于兩個(gè)不同的概念,根據(jù)ISP原則應(yīng)該把它們分別定義在代表這兩個(gè)概念的抽象類中。定義方式有:這兩個(gè)概念都使用 abstract class方式定義;兩個(gè)概念都使用interface方式定義;一個(gè)概念使用abstract class方式定義,另一個(gè)概念使用interface方式定義。


    顯然,由于Java語言不支持多重繼承,所以兩個(gè)概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對于它們的選擇卻反映出對于問題領(lǐng)域中的概念本質(zhì)的理解、對于設(shè)計(jì)意圖的反映是否正確、合理。我們一一來分析、說明。


    如 果兩個(gè)概念都使用interface方式來定義,那么就反映出兩個(gè)問題:1、我們可能沒有理解清楚問題領(lǐng)域,AlarmDoor在概念本質(zhì)上到底是 Door還是報(bào)警器?2、如果我們對于問題領(lǐng)域的理解沒有問題,比如:我們通過對于問題領(lǐng)域的分析發(fā)現(xiàn)AlarmDoor在概念本質(zhì)上和Door是一致 的,那么我們在實(shí)現(xiàn)時(shí)就沒有能夠正確的揭示我們的設(shè)計(jì)意圖,因?yàn)樵谶@兩個(gè)概念的定義上(均使用interface方式定義)反映不出上述含義。


    如 果我們對于問題領(lǐng)域的理解是:AlarmDoor在概念本質(zhì)上是Door,同時(shí)它有具有報(bào)警的功能。我們該如何來設(shè)計(jì)、實(shí)現(xiàn)來明確的反映出我們的意思呢? 前面已經(jīng)說過,abstract class在Java語言中表示一種繼承關(guān)系,而繼承關(guān)系在本質(zhì)上是"is a"關(guān)系。所以對于Door這個(gè)概念,我們應(yīng)該使用abstarct class方式來定義。另外,AlarmDoor又具有報(bào)警功能,說明它又能夠完成報(bào)警概念中定義的行為,所以報(bào)警概念可以通過interface方式定 義。如下所示:


    abstract class Door {
    abstract void open();
    abstract void close();

    }
    interface Alarm {
    void alarm();
    }
    class AlarmDoor extends Door implements Alarm {
    void open() { … }
    void close() { … }
    void alarm() { … }
    }

     
    這 種實(shí)現(xiàn)方式基本上能夠明確的反映出我們對于問題領(lǐng)域的理解,正確的揭示我們的設(shè)計(jì)意圖。其實(shí)abstract class表示的是"is a"關(guān)系,interface表示的是"like a"(“has a”)關(guān)系,大家在選擇時(shí)可以作為一個(gè)依據(jù),當(dāng)然這是建立在對問題領(lǐng)域的理解上的,比如:如果我們認(rèn)為AlarmDoor在概念本質(zhì)上是報(bào)警器,同時(shí)又具 有Door的功能,那么上述的定義方式就要反過來了。
    posted on 2007-12-16 11:33 xyz 閱讀(465) 評論(0)  編輯  收藏 所屬分類: 網(wǎng)絡(luò)文摘

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    留言簿

    隨筆檔案(1)

    文章分類(44)

    文章檔案(46)

    收藏夾(1)

    Adobe

    AOP

    API

    appServer

    BI

    c

    • c-free
    • codeblocks
    • codelite
    • CodeLite IDE 是一個(gè)強(qiáng)大的開源,跨平臺的 C/C++整合開發(fā)環(huán)境. 支持包括 Windows、Linux 和 Mac 系統(tǒng)下運(yùn)行
    • codelite官網(wǎng)
    • dev-c++
    • Dev-C++是一個(gè)C&C++開發(fā)工具,它是一款自由軟件,遵守GPL協(xié)議。
    • GCC
    • GCC 原名為 GNU C 語言編譯器(GNU C Compiler),因?yàn)樗局荒芴幚?C語言。GCC 很快地?cái)U(kuò)展,變得可處理 C++。之后也變得可處理 Fortran、Pascal、Objective-C、Java, 以及 Ada 與其他語言。

    Cache

    CMS

    DB

    eclipse

    FreeMarker

    hibernate

    html5

    ibatis

    java

    jquery

    js

    json

    Linux

    Log

    mail server

    mobile

    mysql

    oauth

    openID

    other

    PHP

    portal

    report

    Scheduler

    schema

    Security

    SOA

    spring

    struts

    UI原型設(shè)計(jì)

    w3c

    Wap

    webservice

    xml

    供應(yīng)鏈管理

    博客鏈接

    好網(wǎng)站

    工作流

    開源網(wǎng)

    招聘

    插件下載

    操作系統(tǒng)

    構(gòu)建可伸縮的系統(tǒng)

    構(gòu)建工具

    測試

    • IETest
    • IE官網(wǎng)
    • OpenSTA
    • Siege
    • Siege是一個(gè)壓力測試和評測工具,設(shè)計(jì)用于WEB開發(fā)這評估應(yīng)用在壓力下的承受能力

    游戲

    源碼托管

    經(jīng)營

    資源

    金融/財(cái)務(wù)

    搜索

    •  

    最新評論

    主站蜘蛛池模板: 亚洲成人免费网站| 亚洲精品无码99在线观看| 在线免费中文字幕| 99精品视频在线观看免费专区| 亚洲av手机在线观看| 国内自产拍自a免费毛片| 免费的涩涩视频在线播放| 免费看无码自慰一区二区| 国产精品嫩草影院免费| 国产一区二区三区在线免费观看| 久久久久国色AV免费观看| 精品无码国产污污污免费网站国产| 亚洲精品熟女国产| 亚洲AV成人噜噜无码网站| 亚洲H在线播放在线观看H| 中文文字幕文字幕亚洲色| 亚洲精品久久无码| 日本特黄特色AAA大片免费| 国产精品福利片免费看| 爱丫爱丫影院在线观看免费| 亚洲免费在线播放| 一区二区无码免费视频网站| 永久免费视频v片www| 午夜亚洲国产成人不卡在线| 中文字幕亚洲激情| 亚洲欧洲日产国产综合网| 亚洲一区二区三区四区视频 | 特级av毛片免费观看| 免费激情网站国产高清第一页| 亚洲人成影院77777| 亚洲av乱码一区二区三区按摩| 亚洲妓女综合网99| 国产亚洲玖玖玖在线观看| 白白色免费在线视频| 免费毛片在线看不用播放器 | 亚洲一区影音先锋色资源| 亚洲第一页在线观看| 亚洲精华国产精华精华液好用 | 国产亚洲一区二区手机在线观看| 国产免费av片在线无码免费看| 青青草免费在线视频|