CodeGym /課程 /JAVA 25 SELF /介面概念與宣告語法

介面概念與宣告語法

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

1. 什麼是介面?

如果抽象類別是房子的藍圖,介面更像是一份合約或「契約」,用來要求完成特定的工作。比如你請水電工,你會期待他能「修水龍頭」與「排除漏水」。至於他要怎麼做—你不在意,重點是結果要達成。在 Java 中,介面正是這樣的契約:它說明必須實作哪些方法,但不告訴你如何實作。

重點速覽:

介面 是 Java 中的一種特殊型別,定義了一組方法;凡是簽署(實作)該介面的類別,都必須實作這些方法。

  • 介面只描述「要做什麼」,而不是「怎麼做」。
  • 在 Java 8 之前,介面不包含方法實作。
  • 介面是純粹的契約:如果類別實作介面,就必須實作其所有方法。

為什麼這麼方便?

  • 可以把多個介面「套用」到同一個類別上—也就是讓它同時扮演多種角色。
  • 有助於建立彈性且可擴充的架構,讓類別能實作不同能力。
  • 介面在 Java 標準程式庫中廣泛使用(例如 ComparableSerializableRunnable 等)。

2. 介面宣告的語法

在 Java 宣告介面—簡單至極。使用關鍵字 interface。在 Java 8 之前,介面方法預設視為 public abstract,即使沒有明寫。這表示:該方法必須在實作此介面的類別中予以實作。

介面範例


public interface Movable {
    void move(int x, int y);
}
  • 這裡我們宣告了介面 Movable(可理解為「可移動的」或「能移動的」)。
  • 裡面宣告了方法 move(int x, int y)。沒有方法本體—只有簽章。這就是「契約」: 「如果你實作 Movable,就請實作 move」。

語法要點

  • 介面中的方法在 Java 8 之前不包含本體
  • 介面中的所有方法預設皆為 public abstract(可以不必明寫)。
  • 介面只能包含常數(public static final),不能有一般欄位。

常數範例

public interface Constants {
    int MAX_SPEED = 100; // 預設即為 public static final
}

3. 介面與類別的差異

介面不是類別!來看看差別在哪裡。

類別(包含抽象類別) 介面
可以包含欄位(狀態) 不可包含欄位(只能有常數)
可以包含方法實作 在 Java 8 之前介面不能包含實作,只有簽章
可以透過 new 建立實例(若非抽象) 不能直接建立實例
只能單一繼承(extends 類別可以實作多個介面(implements
用來表達「它是什麼」 用來表達「它能做什麼」

類別透過 implements 來實作介面

public class Robot implements Movable {
    @Override
    public void move(int x, int y) {
        System.out.println("機器人移動到點 (" + x + ", " + y + ")");
    }
}
  • 類別 Robot 實作了介面 Movable
  • 關鍵字 implements — 「實作」。
  • 必須實作介面的所有方法(否則會有編譯錯誤)。
  • 別忘了註解 @Override — 它不是必需,但能幫助編譯器與你避免失誤。

4. 介面使用範例

寫個簡單範例,看看實際如何運作。假設我們有介面 Movable,並希望不同類別都能「移動」:機器人、汽車、動物……

步驟 1:宣告介面

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

步驟 2:在類別中實作介面

public class Robot implements Movable {
    @Override
    public void move(int x, int y) {
        System.out.println("機器人移動到點 (" + x + ", " + y + ")");
    }
}

步驟 3:使用介面

public class Main {
    public static void main(String[] args) {
        Movable m = new Robot(); // 介面型別的變數!
        m.move(10, 20); // 將輸出:機器人移動到點 (10, 20)
    }
}

請注意

  • 我們可以宣告介面型別的變數(Movable m),並將實作該介面的類別物件指派給它(new Robot())。
  • 這使我們能撰寫通用的程式碼,能與任何「可移動」的物件合作,而不必知道它實際是哪個類別。

未實作方法時的編譯錯誤

Error: Class 'Robot' must either be declared abstract or implement abstract method 'move(int, int)' in 'Movable'

這就是介面的威力 — 它保證所有實作的類別都具備所需的方法。

5. Java 標準程式庫中的介面

介面不是「課本上的」概念而已。它們在整個 Java 標準程式庫中都被大量使用。以下是幾個例子:

  • Comparable<T> — 用於比較物件的介面(例如用於排序)。
  • Runnable — 啟動執行緒的介面。
  • Serializable — 標記(marker)介面,表示物件可被序列化。
  • ListSetMap — 集合的介面。

範例:Comparable

public class Person implements Comparable<Person> {
    String name;
    int age;

    // 建構子與其他方法...

    @Override
    public int compareTo(Person other) {
        return this.age - other.age;
    }
}

現在物件 Person 可以被排序,因為它們實作了介面 Comparable

6. 視覺示意:介面如何運作

+-------------------+         +-------------------+
|   interface       |         |    class          |
|   Movable         |<--------|    Robot          |
|-------------------|         |-------------------|
| +move(int, int)   |         | +move(int, int)   |
+-------------------+         +-------------------+
  • 箭頭表示類別 Robot 實作了介面 Movable
  • 介面只規定「應該有什麼」,類別負責「如何運作」。

生活中的類比

在 Java 中,介面就像駕照。若你持有駕照(你實作了「駕駛員」這個介面),代表你駕駛汽車。至於你怎麼開—有人小心、有人迅速—那是細節;重點是你已承諾自己會做這件事。

7. 實作範例:延續我們的應用

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

public class Animal implements Movable {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    @Override
    public void move(int x, int y) {
        System.out.println(name + " 移動到點 (" + x + ", " + y + ")");
    }
}

public class Robot implements Movable {
    private String model;

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

    @Override
    public void move(int x, int y) {
        System.out.println("機器人 " + model + " 開往座標 (" + x + ", " + y + ")");
    }
}

public class Main {
    public static void main(String[] args) {
        Movable[] movables = {
            new Animal("Barsik"),
            new Robot("R2D2")
        };

        for (Movable m : movables) {
            m.move(5, 10);
        }
    }
}

結果:

Barsik 移動到點 (5, 10)
機器人 R2D2 開往座標 (5, 10)

我們建立了一個 Movable 型別的物件陣列。裡面可以放入任何實作該介面的物件!迴圈中的程式碼不知道眼前的是動物還是機器人,但知道每個物件都會 move

8. 使用介面時的常見錯誤

錯誤 1:嘗試直接建立介面的實例。 介面是契約,而非具體物件。不能寫 new Movable() — 這會導致編譯錯誤。應該建立實作該介面的類別的物件。

錯誤 2:沒有實作介面的所有方法。 若類別實作了介面,卻未實作其所有方法,編譯器會報錯:「Class must either be declared abstract or implement abstract method ...」。如果你不想實作所有方法—就把類別宣告為 abstract

錯誤 3:忽略了存取修飾子。 介面的方法一律是 public(即使未明寫)。在實作的類別中不可降低存取層級,因此方法也必須是 public

錯誤 4:試圖在介面中加入一般欄位。 介面只能宣告常數(public static final)。不能加入一般(非靜態)的欄位。

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