2008-11-27 57 views

回答

20

抽象類是用來當你打算創建一個具體類, 但要確保有在所有子類 一些常見的狀態或對某些操作可能共同實施

接口不能包含任何一個。

+0

即使定義了抽象類,我也會繼續定義接口。它使你的代碼更友善,並且更少地耦合到特定的實現。 – tvanfosson 2008-11-27 04:58:44

+0

是的,當然,我同意100%。在我的代碼中,我通常將接口界定爲接口(聽起來很愚蠢),並使用抽象類作爲標準實現和狀態的基礎。 – Uri 2008-11-27 05:09:22

+0

你說:「並且使用抽象類作爲標準實現的基礎和狀態 你可能的意思是: 」並且使用抽象類作爲「普通實現」的基礎和狀態「 – Shaw 2008-11-27 06:36:41

4

抽象類v/s接口是一個話題,對於任何新來的Java人都會產生很多好奇心/興趣/困惑,並想深入挖掘。

This article提供了關於該主題的詳細解釋。

8

是的,有抽象類和接口的地方。

讓我們來舉一個具體的例子。我們將研究如何從摘要AbstractBankAccount製作CheckingAccountSavingsAccount,並瞭解我們如何使用界面區分這兩種類型的帳戶。

要開始了,這裏是一個抽象類AbstractBankAccount

abstract class AbstractBankAccount 
{ 
    int balance; 
    public abstract void deposit(int amount); 
    public abstract void withdraw(int amount); 
} 

我們的帳戶餘額balance和兩個方法depositwithdraw必須由子類實現。

正如我們所看到的,抽象類聲明瞭應如何定義銀行帳戶的結構。正如@Uri在他的回覆中提到的,這個抽象類有狀態,它是balance字段。這對於一個界面來說是不可能的。

現在,讓我們的子類AbstractBankAccount做出CheckingAccount

class CheckingAccount extends AbstractBankAccount 
{ 
    public void deposit(int amount) 
    { 
     balance += amount; 
    } 

    public void withdraw(int amount) 
    { 
     balance -= amount; 
    } 
} 

在這一小類CheckingAccount,我們實施了兩個抽象類 - 沒有什麼太有趣了這裏。

現在,我們該如何執行SavingsAccount?它不同於CheckingAccount,因爲它會獲得利益。通過使用deposit方法可以增加興趣,但是再一次,它不像顧客自己放置興趣。因此,如果我們有另一種向賬戶中添加資金的手段,特別是爲了利息,比如說,可以更清楚地說明一種方法。

我們可以直接實現方法SavingsAccount,但我們可能能夠在未來的計息更多的銀行帳戶類型,所以我們可能要做出InterestBearing接口具有accrueInterest方法:

interface InterestBearing 
{ 
    public void accrueInterest(int amount); 
} 

所以,我們現在可以做出SavingsAccount類可以通過實現InterestBearing接口獲得利益:現在

class SavingsAccount extends AbstractBankAccount implements InterestBearing 
{ 
    public void deposit(int amount) 
    { 
     balance += amount; 
    } 

    public void withdraw(int amount) 
    { 
     balance -= amount; 
    } 

    public void accrueInterest(int amount) 
    { 
     balance += amount; 
    } 
} 

,如果我們想使anothe r類型的賬戶,例如PremiumSavingsAccount,我們可以製作AbstractBankAccount的子類並實現InterestBearing接口以創建另一個有息賬戶。

InterestBearing接口可以看作是將一個共同特徵添加到不同的類。在沒有任何利息的情況下,擁有一個功能來處理支票賬戶中的利息是沒有意義的。

所以,的確是有兩個抽象類和接口共存,並且在一種情況下一起工作的地方。

0

在一般情況下,接口描述,你的代碼應該使用公共API,而抽象基類最好保存爲一個實現細節,可以保留常見的代碼或狀態,以減少任何實現類中的重複。

通過在您的API中使用接口,人們(包括您)可以更輕鬆地針對您的類編寫測試代碼,因爲您可以使用測試類,例如,不依賴於任何外部資源,或者展現出明顯的壞 - 但是難以模擬的現實生活行爲。

所以Java提供了List接口,而AbstractList的抽象基類,以「最大限度地減少實現所需的努力」的界面...

2

有幾個原因,你可能更喜歡無實現的抽象類通過接口:

  • 某些不可能的強制轉換和instanceof操作可以在編譯時捕獲。
  • 您可以選擇在更高版本中添加具體方法。
  • 許多年前曾經有一個顯着的性能優勢。
  • 從一個不起眼的高度安全的角度看,你不能讓一個已經存在的類創建預先存在的類的子類和抽象類來實現的方法。

但在另一方面,該接口的Java關鍵字允許更清潔源。