接口與抽象類的區別和存在意義


接口 和抽象類 的區別在面試中問的比較廣泛,同時也是開發者必須要明白的基礎性知識,下面就來捋一下:

從特征上比較
(1)接口可被類實現(implement),也可以被接口擴展繼承(extends),抽象類只能被子類繼承(extends)。
(2)接口只能有方法聲明和不可變常量:
方法聲明:會被自動設置為public abstract,接口中方法平時會省略掉public,但是實現方法必須顯示聲明public;
不可變常量:定義的變量只能是公共的靜態的常量,域變量會被自動設置為public static final;

/**
 * 菜單接口
 */
public interface MenuService {         //接口名 補全public
 
  int defaultTotal=33;                       //1.1:一般寫法
  public static final int defaultTotal2=40;  //1.2:常量補全public static final,和上面類型相同
 
  Double getFoodTotal(String restaurantName);       //2.1:一般寫法
  abstract Double getFoodPrice(String foodName);    //2.2:方法聲明補全抽象方法關鍵詞abstract
  public abstract int getFoodNum(String foodName);  //2.3:方法聲明補全抽象方法關鍵詞public abstract
 
 
  default String getBaseInfo(){        //3.1:java8 引入默認方法,必須實現
      //defaultTotal=defaultTotal+1;       //錯誤,長嶺不能更改
        return "This is a menu";
    }
  static String getRestaurantName(){   //3.2:java8 引入靜態方法,必須實現
        return "MFC";
    }
}

 抽象類可以有方法聲明(即抽象方法)、具體的方法和屬性(可以是靜態常量和普通變量)。

/**
 * 菜單抽象類  //補充public,abstract可以省略,只要有抽象方法就是一個抽象類
 */
public  abstract class MenuAbstract {
    int defaultTotal=33;                       //1.1:變量
    public static final int defaultTotal2=40;  //1.2:常量,和上面的變量不同
 
    //Double getFoodTotal(String restaurantName);      //2.1:方法聲明錯誤用法,abstract聲明的類中抽象方法必須使用abstract
    abstract Double getFoodPrice(String foodName);    //2.2:方法聲明一般寫法
    public abstract int getFoodNum(String foodName);  //2.3:方法聲明補全關鍵詞public
 
    public String getBaseInfo(){  //2.4:具體方法,public可省略
        defaultTotal=defaultTotal+1;
        return "This is a menu";
    }
    static String getRestaurantName(){  //2.5
        return "MFC";
    }
//    default String getBaseInfo(){    //2:抽象方法不支持默認default方法
//        return "This is a menu";
//    }
}

(3)用instanceof可以檢查一個對象是否屬於某個特定類或是否實現了某個接口。可用來檢測是否實現了目標接口或目標類。
(4)Java8新添加相關特性:
》》》接口可以含有靜態方法,但必須實現該靜態方法。
值得注意的是:實現類實現多個接口時,可能會實現多個接口,各個接口可能含有同參同名的方法,使用該方法時,要使用“接口.接口靜態方法”,而不是“實現類.接口靜態方法”;如果接口要定義同名同參的靜態方法,但是不能使用@Override重寫接口中的方法,使用“實現類.實現類靜態方法”的形式訪問即可實現類中的靜態方法。
》》》接口中可以含有默認方法,但必須實現它。


從設計上做比較
(1)接口和抽象類都是用來抽象具體對象的,兩者均能體現多態性,但是接口的抽象級別最高,兩者均不可直接實例化,若要實例化,必須先實現所有抽象方法。
(2)接口是設計的結果,即從無到有,大家制定契約和規則,簽約類必須要完全遵守、實現該契約中的方法,即所有方法都是有意義且必須要實現的;側重於行為約束,主要抽象功能。
抽象類是重構的結果,即從有到有 的設計,更側重與內部優化與合理性,是為了繼承擴展,實現代碼的重用,主要抽象了事物(包含屬性和方法)。

如何理解上面代碼中的菜單的設計?
當一家餐廳可能有多個門店,每個門店可能需要根據當地的實際消費,人數等情況自定義價格,折扣等操作,所以就出現了不同的需求。
菜單接口:由專門人員去設計,3個開發者根據接口去開發,每個人負責一種門店菜單的開發,接口從無到有,要求所有門店菜單開發者(實現者)必須遵守這樣的接口,實現每個方法,側重於契約精神、規則精神。
菜單抽象類:可以將所有門店的共同行為或屬性抽取出來放在抽象類,派生的門店菜單實現類就不需要多次重寫相同的行為代碼了;並且,不同門店的個性化需求,可以通過實現抽象方法自定義;

為什么要設計接口和抽象類?
接口設計不是必須的,如果一個系統較為復雜,需要多人合作,則可以使用接口,設計者制定接口后,就不再輕易改變接口(除非改動對接口有意義),其他人根據接口具體實現即可。如果系統較為簡單,一個人即可實現,無需設計接口,否則就要牽一發動全身。不用為了以后的擴展怎么滴怎么滴的大費周章的去設計,真到那個時候再去重構設計也不遲。
抽象類的設計也不是必須的,它的設計師為了更好的優化重構代碼,實現代碼的擴展、復用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM