2008-12-09 113 views
7

我有一個接口A,爲此我必須提供一些不同的 實現。但是,這些實現共享一些幫助器方法,所以我將這些方法移到了抽象基類中。實現與抽象類的接口時聲明什麼(不)?

Interface A { 
    void doX(); 
} 

abstract Class B implements A { 
    protected void commonY() { 
     // ... 
    } 

    @Override 
    public abstract void doX(); 
} 

Class C extends B { 
    @Override 
    public void doX() { 
     // ... 
    } 
} 

Class D extends B { 
    @Override 
    public void doX() { 
     // ... 
    } 
} 

我的代碼工作正常,但我有幾個問題:

  • 我應該聲明抽象方法DOX()B類?爲什麼不)?

  • 我是否還應該在類C和D上顯式聲明「implements A」?爲什麼不)?

回答

8

我認爲這將是更好地做到這一點,如下所示:

Interface A { 
     void doX(); 
} 

abstract Class B { 
     protected void commonY() { 
       // ... 
     } 
} 

Class C extends B implements A{ 

     public void doX() { 
       // ... 
     } 
} 

Class D extends B implements A{ 

     public void doX() { 
       // ... 
     } 
} 

你不應該混合與實現接口(方法簽名)。

+0

此解決方案的好處是,當實現Z的類X實現時,需要方法commonY的功能,它可以專用類B. – 2008-12-09 11:59:03

4
  • 我應該聲明的抽象方法DOX()在B類?爲什麼不)?

不是。它是一個抽象類 - 定義接口意味着所有的子類都需要實現這些方法。換句話說,這是多餘的。

  • 我是否也應該在類C和D上顯式聲明「implements A」?爲什麼不)?

不,再次 - 因爲您的超類(抽象基類)實現了該接口,您的具體子類將保證實現該接口。

0

實現接口的抽象類必須實現該接口。具體而言,它必須爲該接口中指定的每個方法名稱和簽名提供公共方法。

繼承是可傳遞的。如果C類派生了實現接口A的類B,則不需要編寫該類實現接口A.但是,它也沒有太大的危害。

+0

我不認爲抽象類必須實現接口中的每個方法。我剛剛測試過這個,看起來你可以在抽象類中實現一個接口,而不需要實際聲明任何接口的方法。 – 2008-12-09 11:48:44

+0

嗯,你可能是對的。我正在離開我對Java的記憶以及我目前在C#中的經驗。在C#中,需要一個實現接口的抽象類來實現所有接口方法(即使只是將它們標記爲抽象)。 – yfeldblum 2008-12-09 12:16:06

0

我不會B聲明doX()因爲你應該not repeat yourself不是CD添加「implements A」。

B中的摘要doX()什麼也沒加,因爲它已經由「implements A」指定。將「implements A」添加到CD也是如此。

對這些條款的唯一可能的用途是文檔:如果你想讓它非常明確的是C(或D)是-A A,那麼你可以添加implements,但你應該知道,它確實沒有按對編譯器無關緊要。

1

我只是拋出另一種選擇。

將抽象類B轉換爲未實現A的AUtil類。方法簽名可能需要類型A的附加參數才能使用。

C和D實現A,並在內部實例化一個AUtil。這確實允許C和D擴展其他類。

1

我同意JeeBee:考慮在抽象基類以外的地方實現你的幫助器方法。

如果您的幫助器方法commonY()僅存在於抽象基類B中,那麼實現接口A的所有類也必須擴展基類B以利用commonY()的實現。但是,您可能並不總是希望被迫擴展B級。

另外,如果您想在將來更改commonY()的實現,該怎麼辦?然後,您將影響接口A的大量實現。但是,如果您不控制接口A的所有這些實現,則可能會影響其功能(糟糕的方式)而無意。

在這種情況下使用抽象基類可能會簡單地帶走一些靈活性,而不會給你任何回報。