從設計層面上談談抽象類和介面的區別

2021-10-10 01:39:58 字數 3483 閱讀 8310

為什麼想談談抽象類和介面呢?

介面的方法預設是public,所有的方法在介面中不能有實現(jdk8開始方法可以實現,不過要增加static或者default修飾符);而抽象類可以有非抽象的方法,也就是可以實現方法,也就是方法可以有方法體。

乙個類能實現多個介面,但是乙個類只能繼承乙個抽象類。

從方法上來說,介面中的方法預設以public abttact 修飾,而抽象類中的抽象方法可以有 public、protected 和 default 這些修飾符(抽象方法就是為了被重寫所以不能使用 private 關鍵字修飾)。

從屬性上來說,抽象類中的屬性可以用各種各樣的修飾符去修飾,而介面中的屬性預設是public static final。

抽象類可以含有構造方法,而介面不可以有構造方法。

jdk7~jdk9期間,介面發生的變化:

在 jdk7或更早版本中,介面裡面只能有常量變數和抽象方法。這些介面方法必須由選擇實現介面的類實現。

jdk8的時候介面可以有預設方法和靜態方法功能。

jdk9在介面中引入了私有方法和私有靜態方法。

以上回答都是基於介面和抽象類使用上的區別來說明的,當看到這麼多區別的時候,我又覺得這兩者是那麼的相似,為什麼有了介面還會有抽象類呢?什麼時候會用到抽象類,什麼時候又會用到介面呢?

於是有了介面和抽象類在設計層面上的區別。

先來舉乙個簡單的例子:

學生和老師都有吃飯、寫字的本領吧,就下面這樣:

class

student

public

void

sleep()

}class

teacher

public

void

sleep()

}

這樣student和teacher都有重複的**,那麼我們有兩個辦法:

可以定義乙個介面,介面裡面包含了eat()和sleep()方法,然後讓student和teacher都實現這個方法就好了。

可以定義乙個抽象類,抽象類裡面包含了eat()和sleep()方法,然後讓student和teacher都繼承這個抽象類就好了。

這樣一看,抽象類和介面似乎沒什麼區別。

但是如果給teacher增加乙個教書的方法teach(),而student是不能教書的,也就沒有teach()方法,那要怎麼解決呢?

如果在介面中增加teach(),那學生實現了這個介面的話,也就具備了teach(),不可行!

如果在抽象類中增加teach(),那學生繼承了這個抽象類的話,也就具備了teach(),不可行!

試想一下eat()和sleep()都是學生和老師共有的方法,那我們可以將eat()和sleep()都寫進乙個抽象類person,然後讓老師和學生都繼承person,teach()是老師獨有的方法,也就是對person的一種拓展和延伸,那我們可以再定義乙個teach介面,然後讓老師去實現這個teach介面,總體解決方案如下:

abstract

class

person

inte***ce

teach

class

student

extends

person

@override

public

void

write()

}class

teacher

extends

person

implements

teach

@override

public

void

write()

@override

public

void

teach()

}

寫到這,應該大部分人能夠明白介面和抽象類的區別了,總的來說:

繼承是乙個 "是不是"的關係,而 介面實現則是 "有沒有"的關係。如果乙個類繼承了某個抽象類,則子類必定是抽象類的種類,而介面實現則是有沒有、具備不具備的關係,比如乙個人是否能教書,能則可以實現這個介面,不能就不實現這個介面。

你以為這樣就完了嗎?

細心的人會說,那為什麼有抽象類,我用乙個普通類person也可以呀,然後讓student和teacher繼承這個person就好了呀,是的, 沒錯,就像這樣:

class

person

public

void

write()

}inte***ce

teach

class

student

extends

person

class

teacher

extends

person

implements

teach

}

不知道你有沒有忘,抽象類中既可以定義未實現的方法,也可以定義實現了的方法。

當不同的類具有某些相同的行為時,且實現的方法一致時,比如說see()都是用眼睛看,hear()都是用耳朵聽,那麼see()和hear()都可以在抽象類中實現,其他的類都派生於這個抽象類,避免了see()和hear()的重複實現,反正大家see()和hear()都是一樣的,這就達到了**復用的目的。

當不同的類具有某些相同的行為時,且實現的方法不一致時,比如說eat(),老師可能在教師餐廳吃,而學生可能在學生食堂吃,這就使得eat()的實現方式是不同的,所以eat()可以作為抽象類中的抽象方法,所有的派生類自己去實現這個eat()方法!

這些,普通的類能做到嗎?如果是普通的類,它的方法必須有方法體,那麼所有派生於普通類的類的方法實現都是整合自父類的(除非方法重寫)!

abstract

class

person

public

abstract

void

eat();

}inte***ce

teach

class

student

extends

person

}class

teacher

extends

person

implements

teach

@override

public

void

eat(

)}

介面的設計目的,是對類的行為進行約束(更準確的說是一種「有」約束,因為介面不能規定類不可以有什麼行為),也就是提供一種機制,可以強制要求不同的類具有相同的行為。它只約束了行為的有無,但不對如何實現行為進行限制。

抽象類的實現目的,是**復用,可以讓這些類都派生於乙個抽象類。在這個抽象類中實現了共有的方法,避免讓所有的子類來實現這個共有的方法,這就達到了**復用的目的。

也談談抽象類和介面的區別

前面有朋友發表過一篇名為 你看不懂的抽象類和介面的區別 的博文,我覺得作者部落格的內容沒有很好的詮釋 你看不懂的抽象類和介面的區別 這個標題。我來說說自己的看法。先舉個例子,以方便大家理解,然後從例子中抽象概括出結論。比如,一家生產門的公司,需要先定義好門的模板,以便能快速生產出不同規格,功能的門。...

抽象類和介面的區別

要結合來使用,從而互補長短。接下來先說說抽象類和介面的區別。區別一,兩者表達的概念不一樣。抽象類是一類事物的高度聚合,那麼對於繼承抽象類的子類來說,對於抽象類來說,屬於 是 的關係 而介面是定義行為規範,因此對於實現介面的子類來說,相對於介面來說,是 行為需要按照介面來完成 這些聽起來有些虛,舉個例...

抽象類和介面的比較

1.抽象類 是一種特殊的類,具有以下特點 a 抽象方法只作宣告,而不包括實現,可以是看成沒有實現體的虛方法。b 抽象類不能被例項化,除此之外,具有類的其他特性。c 抽象類可以但不是不惜具有抽象方法和抽象方法,但是一旦有了抽象方法,就一定要把這個類宣告為抽象類。d 具體派生類必須覆蓋抽象類的抽象方法。...