亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

抽象類和接口有什么區別嗎?

都可以規定類提供某些必須的方法。

正在回答

2 回答

語法層次的我就不介紹了,下面從設計層面談一下區別。

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


使用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??雌饋砗孟袷褂胊bstract class和interface沒有大的區 別。?

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


解決方案一:?

簡單的在Door的定義中增加一個alarm方法,如下:?

abstract?class?Door?{?abstract?void?open();?abstract?void?close();?abstract?void?alarm();?}?或者?

interface?Door?{?void?open();?void?close();?void?alarm();?}?那么具有報警功能的AlarmDoor的定義方式如下:?


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

class?AlarmDoor?implements?Door?{?void?open()?{?…?}?void?close()?{?…?}?void?alarm()?{?…?}?}?這種方法違反了面向對象設計中的一個核心原則ISP(Interface Segregation Priciple ),在Door的定義中把Door概念本身固有的行為方法和另外一個概念"報警器"的行為方 法混在了一起。這樣引起的一個問題是那些僅僅 依賴于Door這個概念的模塊會因為"報 警器"這個概念的改變(比如:修改alarm方法的參數)而改變,反之依然。?

解決方案二:?

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

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

如果兩個概念都使用interface方式來定義,那么就反映出兩個問題:?

1、我們可能沒有理解清楚問題領域,AlarmDoor在概念本質上到底是Door還是報警器??

2、如果我們對于問題領域的理解沒有問題,比如:我們通過對于問題領域的分析發現AlarmDoor在概念本質上和Door是一致的,那么我們在實現時就沒有能夠正確的揭示我們 的設計意圖,因為在這兩個概念的定義上(均使用 interface方式定義)反映不出上述 含義。?

如果我們對于問題領域的理解是:AlarmDoor在概念本質上是Door,同 時它有具有報警 的功能。我們該如何來設計、實現來明確的反映出我們的意思呢?前面已經說過, abstract class在Java語言中表示一種繼承關系,而繼承關系在本質上是"is a"關系。
所以對于Door這個概念,我們應該使用abstarct class方式來定義。另外,AlarmDoor又 具有報警功能,說明它又能夠完成報警概念中定義的行為,所以報警概念可以通過 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()?{?…?}?}?這種實現方式基本上能夠明確的反映出我們對于問題領域的理解,正確的揭示我們的設計 意圖。其實abstract class表示的是"is a"關系,interface表示的是"like a"關系,大家在選擇時可以作為一個依據,當然這是建立在對問題領域的理解上的,比如:如?
果我們認為AlarmDoor在概念本質上是報警器,同時又具有 Door的功能,那么上述的定義方式就要反過來了。?

abstract class和interface是Java語言中的兩種定義抽象類的方式,它們之間有很大的 相似性。但是對于它們的選擇卻又往往反映出對于問題領域中的概 念本質的理解、對于 設計意圖的反映是否正確、合理,因為它們表現了概念間的不同的關系(雖然都能夠實 現需求的功能)。這其實也是語言的一種的慣用法。?

9 回復 有任何疑惑可以回復我~
#1

喵喵E

解決方案一那里的class AlarmDoor extends Door { void open() { … } void close() { … } void alarm() { … } } 或者 class AlarmDoor implements Door { void open() { … } void close() { … } void alarm() { … } } 第一個代碼是不是abstract Door啊?怎么都一樣呢?
2018-04-26 回復 有任何疑惑可以回復我~
#2

喵喵E 回復 喵喵E

我知道了看錯了
2018-04-26 回復 有任何疑惑可以回復我~

1、抽象類里面可以有非抽象方法
但接口里只能有抽象方法
聲明方法的存在而不去實現它的類被叫做抽像類(abstract class),它用于要創建一個體現某些基本行為的類,并為該類聲明方法,但不能在該類中實現該類的情況。不能創建abstract 類的實例。然而可以創建一個變量,其類型是一個抽像類,并讓它指向具體子類的一個實例。不能有抽像構造函數或抽像靜態方法。Abstract 類的子類為它們父類中的所有抽像方法提供實現,否則它們也是抽像類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法。

2、接口(interface)是抽像類的變體。在接口中,所有方法都是抽像的。多繼承性可通過實現這樣的接口而獲得。接口中的所有方法都是抽像的,沒有一個有程序體。接口只可以定義static final成員變量。接口的實現與子類相似,除了該實現類不能從接口定義中繼承行為。當類實現特殊接口時,它定義(即將程序體給予)所有這種接口的方法。然后,它可以在實現了該接口的類的任何對像上調用接口的方法。由于有抽像類,它允許使用接口名作為引用變量的類型。通常的動態聯編將生效。引用可以轉換到接口類型或從接口類型轉換,instanceof 運算符可以用來決定某對象的類是否實現了接口

0 回復 有任何疑惑可以回復我~

舉報

0/150
提交
取消
Java入門第二季 升級版
  • 參與學習       531142    人
  • 解答問題       6326    個

課程升級!以終為始告別枯燥,在開發和重構中體會Java面向對象編程的奧妙

進入課程

抽象類和接口有什么區別嗎?

我要回答 關注問題
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號