CodeGym /課程 /JAVA 25 SELF /介面與抽象類別的差異

介面與抽象類別的差異

JAVA 25 SELF
等級 20 , 課堂 1
開放

1. 抽象類別:複習基礎

在開始比較之前,先複習一下什麼是抽象類別。

抽象類別——是一種無法直接被建立的類別(不能寫 new Animal()),但它可以同時包含一般方法(有實作)與抽象方法(無實作)。抽象類別常被用作其他類別的基底,子類別會繼承其行為,並且必須實作部分方法。

例如,在應用程式中如果有不同種類的交通工具,可以建立抽象類別 Transport

public abstract class Transport {
    private String model;

    public Transport(String model) {
        this.model = model;
    }

    public String getModel() {
        return model;
    }

    // 抽象方法 — 沒有實作,只有宣告
    public abstract void move();

    // 一般方法 — 有實作
    public void printInfo() {
        System.out.println("交通工具型號: " + model);
    }
}

抽象類別的特性:

  • 可以包含欄位(狀態)。
  • 可以包含已實作的方法。
  • 可以包含抽象方法(子類別必須實作)。
  • 不可直接建立實例。
  • 用於提供共通行為與狀態。

2. 介面:複習基礎

介面是一組類別必須實作的方法。介面不描述狀態(不能有一般欄位,只能有常數),而且在 Java 8 之前不包含方法實作。介面是純粹的合約: 「如果你實作我,你就必須能做這些事」。

介面範例:

public interface Movable {
    void move(int x, int y);
}

介面的特性:

  • 不包含狀態(只允許 public static final 常數)。
  • 在 Java 8 之前——只有抽象方法(自 Java 8 起有 defaultstatic 方法,稍後再談)。
  • 方法預設皆為 public abstract
  • 類別可以實作多個介面。
  • 用於描述能力,類別「會做什麼」。

3. 比較表:抽象類別 vs 介面

是時候把這兩個工具放在一起比較了!以下是直觀的表格:

特性 抽象類別 介面
語法
abstract class
interface
可以建立實例嗎?
可包含一般方法嗎? 在 Java 8 之前——否;自 Java 8 起——僅限 default/static
可包含抽象方法嗎? 是(Java 8 之前所有方法皆為抽象)
可包含欄位(狀態)嗎? 是(任何欄位) 僅限 public static final(常數)
可包含建構子嗎?
繼承 只能有一個抽象/一般父類別 可以實作多個介面
方法的修飾子 任意(publicprotectedprivate 方法預設為 public abstract。自 Java 9 起可在介面內新增 private 方法供內部使用
繼承/實作關鍵字
extends
implements
常見用途 提供共通實作與狀態 描述能力、角色
JDK 範例
AbstractList, AbstractMap
Comparable, Runnable

4. 何時使用介面,何時使用抽象類別?

介面適用於:

  • 你想描述類別「會做什麼」,而不關心它如何實作。
  • 你需要讓類別能實作多個彼此獨立的能力。
  • 例:Comparable(可比較)、Serializable(可序列化)、Runnable(可在執行緒中執行)。

抽象類別適用於:

  • 你想定義所有子類別都會擁有的共通實作與狀態。
  • 你需要所有子類別具備特定欄位,或具有已實作的方法。
  • 繼承嚴格是「一對一」:類別只能繼承一個類別(一般或抽象)。

生活中的類比

  • 介面就像「駕照」:如果你擁有它,你可以開車,但沒有人規定你要開哪一台車、用什麼方式開。
  • 抽象類別就像「汽車的通用藍圖」:所有車都有方向盤、踏板、引擎,但各品牌會以自己的方式實作細節。

5. Java 標準函式庫中的範例

介面:Comparable

public interface Comparable<T> {
    int compareTo(T o);
}

任何實作此介面的類別都必須實作方法 compareTo。例如,StringIntegerLocalDate 等等。

抽象類別:AbstractList

public abstract class AbstractList<E> implements List<E> {
    // 預設實作部分 List 方法
    // 其餘部分方法保持為抽象
}

AbstractList 已經實作了部分集合的行為(例如新增/刪除的方法),但仍保留一些方法為抽象,以便子類別能依自身需求實作。

6. 程式碼範例:實務比較

介面

建立一個介面以及實作它的類別。

public interface Printable {
    void print();
}

public class Document implements Printable {
    @Override
    public void print() {
        System.out.println("正在列印文件...");
    }
}

抽象類別

接著是抽象類別及其子類別.

public abstract class Machine {
    public void turnOn() {
        System.out.println("機器已開機。");
    }

    public abstract void work();
}

public class Printer extends Machine {
    @Override
    public void work() {
        System.out.println("印表機正在列印...");
    }
}

同時使用兩者:類別同時繼承抽象類別並實作介面

public class SmartPrinter extends Machine implements Printable {
    @Override
    public void work() {
        System.out.println("智慧型印表機正在運作...");
    }

    @Override
    public void print() {
        System.out.println("智慧型印表機正在列印...");
    }
}

7. 多重介面實作:為什麼這麼強大

在 Java 中,類別只能繼承一個(abstract 或一般)父類別,但可以實作任意多個介面!這使得架構更具彈性且易於擴充。

public interface Scannable {
    void scan();
}

public class MultiFunctionPrinter extends Machine implements Printable, Scannable {
    @Override
    public void work() {
        System.out.println("多功能印表機正在運作...");
    }

    @Override
    public void print() {
        System.out.println("多功能印表機正在列印...");
    }

    @Override
    public void scan() {
        System.out.println("多功能印表機正在掃描...");
    }
}

該如何選擇?

  • 若你要設計具備共用狀態(例如欄位)的基礎功能,請使用抽象類別
  • 若你想為物件加上「能力標籤」(例如「會列印」、「可比較」、「可序列化」)——請使用介面
  • 如果不確定——先從介面開始。在 Java 中這被視為良好習慣:介面帶來更高的彈性與可擴充性。

8. 常見錯誤與陷阱

錯誤 №1:嘗試繼承多個類別——Java 不允許!
類別只能繼承一個類別,但可以實作多個介面。例如,class A extends B, C——錯誤;而 class A extends B implements X, Y, Z——可以。

錯誤 №2:把介面與類別的欄位搞混。
在介面中只能宣告常數(public static final)。不能宣告一般的狀態,例如,private int count;——編譯器會立刻阻止你。

錯誤 №3:沒有實作介面中的所有方法.
如果某個類別沒有實作介面中的任何一個方法——它必須宣告為 abstract,否則編譯器會報錯。

錯誤 №4:嘗試建立介面或抽象類別的實例.
這兩種型別都是「半成品」。它們只能被擴充,不能直接被建立:

Printable p = new Printable(); // 錯誤!
Machine m = new Machine();     // 錯誤!

錯誤 №5:以為介面可以有建構子。
介面不能有建構子,因為它們不描述物件的狀態。只有類別(一般與抽象)才有建構子。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION