簡體   English   中英

為什么使用抽象類而不是接口?

[英]Why use abstract class and not interface?

例如,房地產建造者正在建造一個有許多單位的公寓。 除卧室外,公寓的所有客房均采用相同的設計。 卧室設計留給擁有公寓的人們,即; 床的房間可以是不同的設計,適合不同的公寓。

我可以通過如下的abstract類來實現這一點:

public abstract class Flat
{
    //some properties

    public void livingRoom(){
       //some code
    }

    public void kitchen(){
       //some code
    }

    public abstract void bedRoom();

    }
}

implementation類如下:

public class Flat101 extends Flat
{
    public void bedRoom() {
        System.out.println("This flat has a customized bedroom");
   }        

}

或者,我可以使用interface而不是abstract類來實現相同的目的,如下所示:

class Flat
{
  public void livingRoom(){ 
       System.out.println("This flat has a living room");
  }

  public void kitchen(){
     System.out.println("This flat has a kitchen");
  } 
}

interface BedRoomInterface
{
  public abstract void bedRoom();
}

public class Flat101 extends Flat implements BedRoomInterface
{
   public void bedRoom() {
    System.out.println("This flat has a customized bedroom");
   }
}

現在的問題是:為什么應該選擇使用interface (或)為什么我應該選擇使用abstract類?

這取決於您的意圖或用例。 但總的來說,你應該更喜歡接口而不是抽象類 (Bloch的Effective Java中的第18項)。 抽象類更脆弱,因為有人可能會修改抽象類來改變從中擴展的其他類的行為(這是一般性陳述)。

使用接口更靈活,因為如果你有BedroomInterface和LivingRoomInterface,那么你可以讓FlatInterface實現兩個接口,然后Flat101實現類實現FlatInterface(而不是從Flat擴展然后實現接口)。 這看起來更清晰,后來你可以擁有ExecutiveFlatInterface,不僅有卧室和起居室,還有猜測空間,那么Flat102可以實現它。

選項2是讓Flat101從Flat延伸,然后Flat實現BedroomInterface和LivingRoomInterface。 這實際上取決於您想要做什么以及可能需要哪些方法。

如果您正在設計一個將被廣泛使用的API,您將同時使用:通過實現類來表達要實現的契約的接口,以及部分實現該接口並因此允許代碼重用的抽象類。

作為一個例子,考慮Java的List:Collections框架中的方法(例如Collections.sort())是根據List接口編寫的,它部分由抽象類AbstractList實現,而AbstractList又擴展到具體實現LinkedList和ArrayList。 LinkedList和ArrayList重用了AbstractList中的代碼,但這並不妨礙某人編寫自己完全獨立的List實現,然后使用Collections.sort()對其進行排序。

也就是說,在很多情況下,這種方法可能過度。 如果您構建的類型層次結構僅在相對較小的范圍內使用,則通常可以使用抽象類。 如果您稍后決定以后想要一個界面,那么它就是一個非常輕松的重構任務來改變它。

抽象類確實有一些優點:

  • 它們允許您使用包/保護修飾符指定抽象方法
  • 它們有助於代碼重用
  • 通過在超類上使用抽象方法和最終方法,它們允許您限制類的子類化方式,這在各種情況下都很有用(另請參見:模板模式)
  • 在IDE中通常更容易理解引用類的代碼(在抽象類類型參數上單擊“打開聲明”通常比在接口類型參數上更有用)

如果您有一個提供派生類所需的某些功能的類,但每個派生類還需要不同的其他功能實現,那么抽象類提供了一種定義公共實現的方法,同時保留派生類所需的特定行為特定於每個派生類。

我覺得這是概括手段; 如果類的屬性和行為在給定包或模塊中很常見,則抽象類最有用。 一個很好的例子是鼓式制動器; 由於所有鼓式制動器的工作原理與在輪鼓內保持制動相同,因此這種行為可以在所有使用鼓式制動器的汽車中繼承。

用於界面; 它更像是規范或合同,迫使你實施其物種形成。 讓我們舉一個建築物模型的例子,它有各種各樣的物種,如門,窗,升......但是當你將模型實施到實際建築物中時,我們需要保持窗口,但內部行為是由(因為寡婦可以)是一個簡單的寡婦或滑動窗口,顏色和材料......)

希望這可以幫助!!

我覺得當我們需要為多個類實現一些常用功能和一些抽象功能時,我們應該使用抽象類。 如果我們看到Flat的例子,我們有一些常見的設計和一些自定義設計,在這種用例中最好使用抽象而不是再次使用接口來實現自定義函數並使用抽象作為派生類不會創建一個額外實例作為普通派生類。

您不能擴展多個類,但可以實現多個接口

如果您需要經常更改設計,那么抽象類更好,因為任何更改都發生在抽象類中,子類中不需要強制實現。 但是如果接口有任何變化,你必須實現實現類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM