2016-08-24 55 views
2

這種設計真的有效嗎? 傳統的應用程序代碼,所以只是在無需重構時試圖重構。界面和抽象類共享相同的方法

public interface Interface { 
public void abc(); 
} 

public abstract class abClass implements Interface{ 
@Override 
public void abc(){ 
throw new UnsupportedOpException(NOT_IMPLEMENTED_MSG); 
} 

public class xyz extends abClass{ 
@Override 
public void abc(){ 
.......//some code here 

} 

我可以擺脫Interface嗎?不知道這個設計背後的初衷是什麼。你什麼時候想在interfaceabstract這兩個班上都有same methods,最終得到overriden

+3

其實際使用這種接口的良好做法。在接口上查找一些信息。 –

+0

好習慣????對於API類是的,否則,只是開銷。 – davidxxx

+0

@davidhxxx這正是我在想太多.. –

回答

0

void abc();必須由抽象類或者繼承類的實現......

沒有機會擺脫掉那個......

如果你願意,你可以移動的空白ABC();通過使最終

  • 塊OT壓倒一切的:作爲抽象類的方法...

    重新定義它和。

  • 委託實施,子類的通過使抽象過的責任..
+0

這就是我的問題,即使我刪除了接口並刪除了抽象類中的'implements接口',也不會破壞代碼。那麼爲什麼我不能在抽象類中定義它呢? –

0

我認爲,從功能設計的角度來看,它的罰款爲是。有implements Interface只是表示該類必須有一個同名的方法。它在abClass中定義的事實意味着您不僅要說從abClass繼承的所有類都必須具有該接口,還需要您不必在每個類中重新定義它,除非您希望覆蓋它。

所以你實際上並不在Interface定義的方法,但是你在做abClass,當你在xyz定義的方法,你重寫方法abClass

+0

感謝您的回覆。但爲什麼我不能擺脫界面?只要抽象類提供了方法定義,就可以通過子類繼承/重寫(如果需要)。 –

+0

你完全可以。但是如果你想定義另一個類,並且讓它有一個類似'abc()'的方法呢?而且由於它是一種不同類型的對象,因此它不會繼承'abClass'中的其他任何方法。你可以簡單地說'implements Interface',它必須有'abc()'。 – Ishnark

+0

示例:接口:'IShape'具有'public void area(int base,int height)'方法。你有抽象類'Quadrilateral'(用'area(int base,int height)'定義)和子類'Square'(它覆蓋area方法)和'Rectangle'(它保留區域方法)。但是你想創建另一個類「三角形」,並且它繼承了四邊形的方法是沒有意義的,因爲它反正會有些不同。所以'三角類實現IShape'將允許你定義一個叫做area的方法。 – Ishnark

0

當抽象類提供您需要的並且抽象類無法提供的內容時,應該在抽象類後面使用接口。
創建一個沒有具體原因的接口,但因爲你認爲interface==OOP帶來開銷並證明你誤解了OOP是什麼。對於你的情況,如果在應用代碼中,你注意到你可以刪除抽象類後面的接口,並且在編譯時沒有真正的影響,你可能想知道接口的抽象不僅僅是一個高架。這可能是有用的,因爲沒用。我會開發它。

使用抽象類後面的接口打開實現的可能性:您可能受益於與接口相關的這個抽象類,但是您也可以在具體類中實現接口而無需受益於抽象類,因此如您所願。根據我們的需要,編寫從A到Z的實現可能是不合適的。

我個人認爲,該接口是一個抽象類,後面有用的有兩種情況:

  • 接口是很常見的,在所有類型的目標具體類的,但 抽象類是相關的並不是所有目標具體類的類型。

例如,當您實現裝飾器時,您有一個共同的接口來表示裝飾類和裝飾器類。
裝飾類有不同的裝飾類的邏輯和數據。所以,我們的裝飾類或裝飾類的抽象類可能會有所不同。

這裏有一個簡單的例子來表示文件的裝飾器。

通用接口:

public interface IDocumentInput { 

    void read(); 

    byte[] getBytes(); 

    String getStringContent(); 

} 

裝飾文件:

public class DocumentInput implements IDocumentInput { 

    private byte[] bytes; 

    public DocumentInput(byte[] bytes) { 
     this.bytes = bytes; 
    } 

    public byte[] getBytes() { 
     return bytes; 
    } 

    public void read() { 
    } 

    public String getStringContent() { 
     return new String(getBytes(),StandardCharsets.UTF_8); 
    } 

} 

用於裝飾抽象類:

public abstract class AbstractDocumentInputDecorator implements IDocumentInput { 

    protected IDocumentInput document; 
    protected byte[] bytes; 

    public AbstractDocumentInputDecorator(IDocumentInput document) { 
     this.document = document; 
    } 

    public byte[] getBytes() { 
     return bytes; 
    } 

    public final String getStringContent() { 
     return new String(getBytes(),StandardCharsets.UTF_8); 
    } 
} 

混凝土裝飾:

public class SecuredDocumentInputDecorator extends AbstractDocumentInputDecorator { 

    public SecuredDocumentInputDecorator(IDocumentInput document) { 
     super(document); 
    } 

    @Override 
    public void read() { 
     document.read(); 
     processUnsecuring(); 
    } 

    private void processUnsecuring() { 
     byte[] originalBytes = document.getBytes(); 
     bytes = Base64.decodeBase64(originalBytes); 
    } 

} 

在這種情況下,引入接口似乎是合乎邏輯的,因爲抽象類不足以表示所有具體類的常見行爲和/或數據。

  • 您希望爲開發人員提供在不依賴抽象類實現的情況下創建自己的接口實現的可能性。一般來說,當你創建一個開放的API時是可取的。 JDK類中的集合很好地說明了這一點。事實上,如果你想創建接口/契約來提高可擴展性,那麼當你只提供一個抽象類時,那些想要創建它們的實現的開發者即使不想要,也被迫使用這個抽象類。這是不可取的。

  • 您使用強制您使用接口的庫。例如,在EJB 3.0和Spring的第一個版本中,使用抽象類或類不允許從其某些功能中受益。