1. 程式人生 > >論Java中的抽象類與介面

論Java中的抽象類與介面

目錄

  • 抽象類和抽象方法
    • 定義
    • 與普通類的區別以及注意點:
    • 抽象類的作用
  • 介面
    • 定義
    • 示例
    • 注意
    • 作用
  • 最後:介面與抽象類的異同
    • 使用場景
  • 感謝
    • 借鑑

抽象類和抽象方法

定義

  • 抽象方法和抽象類都必須被abstract關鍵字修飾。
  • 抽象——abstract,抽象類的方法不一定是抽象的,但抽象方法出現的類一定是抽象類。
//抽象方法,沒有方法體(即沒有{}),只有宣告
abstract void f();
  • 最重要的是:抽象類,抽象既不是真的,所以,抽象類不可以例項化。但可以通過子類的例項化來使用
/**
 * @author yhy
 * 用來完成9.2的練習
 * 驗證抽象類與抽象方法的使用
 */
public class YanZheng {
    public static void main(String[] args) {
//      不能被例項化,抽象類,會報錯
//        ChouXiang chouxi = new ChouXiang() ;
//        可以例項child類
//        即通過繼承其子類來實現不能繼承抽象類
        Child test = new Child();
    }
}
abstract class AbstractChouXiang{
    /**
     * 建構函式
     */
    AbstractChouXiang() {
    }
    /**
     * 定義一個抽象類的抽象方法
     */
    abstract void chouxiang();
}
class Child extends AbstractChouXiang{
   Child(){
       System.out.println("例項時候就打印出來");
   }

    /**
     * 注意這裡不是abstract就不要講方法定義為abstract
     */
    @Override
    void  chouxiang(){
         System.out.println("繼承抽象類");

    }
}
  • 子類可以不是抽象類,但要實現抽象父類中的所有抽象方法,否則必須定義為abstract型別。(下面的程式碼中,我將其子類的重寫方法註釋掉之後,就會報錯must be declared abstract or implentment abstract method)

與普通類的區別以及注意點:

  • 抽象類也是可以與普通類那樣,可以直接extends,區別在於抽象類不能直接例項化,可以通過例項化其子類,通過子類重寫方法實現等——設定抽象方法就是讓子類來實現的,否則毫無意義。

  • 與普通方法的區別

    抽象方法和空方法體的方法不是同一個概念。例如,public abstract void test();是一個抽象方法,它根本沒方法體,即方法定義後面沒有一對花括號;但public void test(){}方法是一個普通方法,它已經定義了方法體,只是方法體為空,即它的方法體什麼也不做,因此這個方法不可使用abstract來修飾。——瘋狂的Java講義

  • abstract不能用於修飾Field,不能用於修飾區域性變數,即沒有抽象變數、沒有抽象Field等說法;abstract也不能用於修飾構造器,沒有抽象構造器,抽象類裡定義的構造器只能是普通構造器。

抽象類的作用

  • 《thinking in java》

    • 抽象類是普通的類與介面之間的一種中庸之道。

    • 抽象方法、抽象類可以使類的抽象性明確起來,告訴使用者和編譯器怎麼使用它們;

    • 同時,抽象類是很好的重構工具,在後期的工作中,可以實現重用性。

  • 體現一種模板的效果,從一群相似的子類提煉出一個抽象類的感覺一樣,提供了一種規範,子類可以在其原來的基礎上進行擴充套件。

  • 抽象父類可以只定義需要使用的某些方法,把不能實現的部分抽象成抽象方法,就是一中留給下一代去實現,一開始沒有能力去實現,那可就給厲害的人去做,留給其子類去實現。

介面

定義

  • 特殊的“抽象類”——介面(interface):比抽象類更加抽象的是介面,在介面中所有的方法都是抽象的。就不能像上面的抽象類一樣還可以有普通方法。
//省略public就變為預設級別,只能在當前包所訪問
public interface Figure { 
//介面中靜態成員變數
String name = "幾何圖形";//省略public static final 
// 繪製幾何圖形方法
void onDraw(); //省略public 這裡是抽象方法
}
  • Java中可以implements多個介面,多繼承的含義便是接入多個介面(繼承只能單繼承)
  • 一個類可以實現一個或多個介面,繼承使用extends關鍵字(但介面只能繼承介面),實現則使用implements關鍵字。

示例

  • JieKou.java
import java.text.SimpleDateFormat;

/**
 * @author yhy
 * 這個是實現介面定義的程式碼,在其它地方去呼叫
 * 這裡的介面不用public的話,其它的包就訪問不了
 */
public interface JieKou {
//   定義了兩個常量
    /**
     * 這裡定義一個df變數來獲取當前時間
     */
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設定日期格式
    String AUTHOR = "yhycoder";
    /**
     * 定義一個介面的方法
     * 這裡的public是多餘的,在接口裡面是自動為public
     */
    /*public*/ void print();
}
  • 使用介面的Java程式碼
//訪問了其它包的介面,就是下面這個地址
import music.daima.ebook.JieKou;
import java.util.Date;

public class UseInterfaces {
    public static void main(String[] args) {
//例項化using類,實現檢視程式碼的執行情況
        Using Shuchu = new Using();
        Shuchu.print();

    }
}

/**
 * 這裡是介面繼承介面
 */
interface Jiekou2 extends JieKou{
    String num = "介面2";
}

/**
 * 這裡是Using類實現了JieKou和Jiekou2介面,逗號隔開
 */
class Using implements JieKou,Jiekou2 {
    /**
     * 重寫了方法,呼叫介面定義的常量
     */
    @Override
    public void print() {
        System.out.println(AUTHOR+"在新的包裡面使用介面的時間:"+df.format(new Date())+" 同時還有"+num);
    }
}

注意

  1. 介面與抽象類一樣都不能被例項化
  2. 實現介面時介面中原有的抽象方法在實現類中必須實現。預設方法可以根據需要有選擇實現(覆蓋)。靜態方法不需要實現,實現類中不能擁有介面中的靜態方法。(Java 8之後)
//InterfaceA.java檔案,定義一個介面 
public interface InterfaceA {
//抽象方法
    void methodA();
    String methodB();
// 預設方法
    default int methodC() {
    return "6666";
    }
// 預設方法
    default String methodD() {
    return "這是預設方法";
    }
// 靜態方法
    static double methodE() {
    return 0.0;
    } 
}

實現介面程式碼

import xxxx.InterfaceA;
public class ABC implements InterfaceA {
    //重寫
    @Override
    public void methodA() {
    }
    @Override
    public String methodB() {
    return "實現methodB方法...";
    }
    //重寫覆蓋,根據自己的需要來。
    @Override
    public int methodC() {
    return 500;
    } 
}
//實現類中不能有介面中的靜態方法,最後一行
public class HelloWorld {
    public static void main(String[] args) {
//宣告介面型別,物件是實現類,發生多型
    InterfaceA abc = new ABC();
// 訪問實現類methodB方法
    System.out.println(abc.methodB());
// 訪問預設方法methodC
    System.out.println(abc.methodC()); 
// 訪問預設方法methodD
    System.out.println(abc.methodD()); 
// 訪問InterfaceA靜態方法methodE,這裡不能通過實現類去使用介面的靜態方法,只能通過介面名呼叫
    System.out.println(InterfaceA.methodE()); 
    } 
}

作用

  1. 規範,在分配不同人的任務時,介面就像是總綱一樣,告訴大家去實現哪些功能模組等。(命名規範都有限制到)

最後:介面與抽象類的異同

不同

  • 介面interface,實現介面則使用implements;抽象類abstract

  • 抽象類可以有普通方法。Java 8 之前介面中只有抽象方法,而 Java 8 之後介面中也可以宣告具體方法,具體方法通過宣告預設方法實現。

  • 介面可以繼承多個,而抽象類不可以。

  • 和類繼承相似,子介面擴充套件某個父介面,將會獲得父接口裡定義的所有抽象方法、常量Field、內部類和列舉類定義。

  • 實現父介面的所有:一個類實現了一個或多個介面之後,這個類必須完全實現這些接口裡所定義的全部抽象方法(也就是重寫這些抽象方法);否則,該類將保留從父介面那裡繼承到的抽象方法,該類也必須定義成抽象類。

  • 介面定義的是一種規範,因此接口裡不能包含構造器和初始化塊定義。接口裡可以包含Field(只能是常量)、方法(只能是抽象例項方法)、內部類(包括內部介面、列舉)定義。但抽象類與普通類一樣,可以有構造器,初始化模組等。

  • 介面只有常量——介面中不能有例項成員變數,介面所宣告的成員變數全部是靜態常量,即便是變數不加 public static final 修飾符也是靜態常量。抽象類與普通類一樣各種形式的成員變數都可以宣告。

相同

  • 都不能直接例項化來使用。
  • 介面和抽象類都可以包含抽象方法,實現介面或繼承抽象類的普通子類都必須實現這些抽象方法。

使用場景

  • 想要多重繼承的時候——介面(功能性強,規範性)

  • 想要底層基礎功能模組不斷改變——抽象類(模板設計)

感謝

才疏學淺,不對的地方多多指教!

借鑑

部落格園的小夥伴

也是園內小