Thursday, March 24, 2022

[Architecture] Abstract VS Interface 差異

類別實作Interface使用關鍵字implements:類別繼承Abstract Class使用關鍵字extends。

// 類別實作Interface

public class ConcreteClass implements InterfaceA { ... }

// 類別繼承Abstract Class

public class ConcreteClass extends AbstractClassC { ... }


Interface只能繼承(extends)Interface;Abstract Class能繼承類別也能實作Interface。

// Interface只能繼承Interface

public interface InterfaceA extends InterfaceB { ... }

// Abstract Class能繼承類別及實作Interface

public abstract class AbstractClassC extends AbstractClassD implements InterfaceC { ... }


類別能實作多個Interface,Interface能繼承多個Interface;類別只能繼承一個Abstract Class。

// Interface能實作多個Intetface

public interface InterfaceA extends InterfaceB, InterfaceC { ... }

// 類別能實作多個介面

public class ConcreteClass implements InterfaceA, InterfaceB { ... }

// 類別只能繼承一個Abstract Class

public class ConcreteClass extends AbstractClassC { ... }


Interface不可有實作方法(除了static method及Java 8的default method);Abstract Class可以有實作方法,也可以有無實作的抽象方法。

public interface InterfaceA {

    void doSomething(); // 方法無實作
    
    // 靜態方法有實作
    static String getSomething() {
        return "Something";
    }
    
    // Java 8 default methods
    default void doSomeStuff() { 
        System.out.println("do some stuff");
    }
    
}
public abstract class AbstractClassC {
    
    void doSomething() {
        System.out.println("do something"); // 方法有實作
    }

    abstract void doStuff(); // 無實作的抽象方法
    
}

Interface中的變數預設(也只能是)public final static;Abstract Class可自訂變數的存取範圍。

public interface InterfaceA {

    int VALUE = 1; // implicit public static final 

}
public abstract class AbstractClassC {
    
    private int value; // 自訂存取範圍

}

Interface的方法預設(也只能是)public;Abstract Class則可自訂方法的存取範圍(但抽像方法不可為private)。

public interface InterfaceA {

    void doSomething(); // implicit public

}
public abstract class AbstractClassC {
    
    // 自訂存取範圍
    private void doSomething() { 
        System.out.println("do something");
    }

    abstract void doStuff(); // 無實作的抽象方法

}


 Abstract:

Abstract Class 一般都是在 Class 程式碼撰寫過程慢慢被發現, 進而從 Class 提升為 Abstract Class

盡量讓 Abstract Class 擁有最多的共用程式碼,盡量減少資料

Abstract Class 不能 Instance。即不能使用 New 關鍵字初始化

Abstract Class 是必須被衍生 Class 覆寫方法

只有參數宣告,沒有實作的方法,稱為 abstract method

某些情況下,雖然有實作,但我們希望強迫子類別必須 override 該方法時,也可以宣告為abstract method。

Interface 裡的方法一定沒有實作,因此必然為 abstract method。

衍生 Class 可以部份實作

如果 Class 中包含 Abstract Method (抽象方法),那麼此 Class 就必須定義為 Abstract Class

繼承 abstract class 的子類別必須 override 所有父類別的 abstract method,否則子類別也必須宣告為 abstract class。

一個 Class 只能繼承一個 Abstract Class


Interface:

Interface 比較像定規格,一般而言都是一開始就設計、定義,也是另一種的「藍圖」,
一開始在什麼都不知道的情況下,預先設計好相關架構

Interface不能 Instance,不能有建構式

不能有修飾詞,Public、Private…等。 (Public Interface)

對宣告中的變數

public: 外界觀看某物件時 ,所能看到的表象以及溝通的管道 ,所以 Interface 內的變數一定是 public。也就是說即便宣告時沒寫 public 關鍵字 ,Compiler 也會幫我們加上去。

final 成員,通常不希望變數會隨便更動

static:

對宣告中的方法

public: 外界觀看某物件時,所能看到的表象以及溝通的管道。同宣告中的變數之 public

abstract: Interface 沒有實作,裡面定義的 method 只是宣告而已。沒有實作的 method,在 Java 裡用 abstract 這個關鍵字來表達。

當 Interface 繼承多個 Interface ,或 Class 實作多個 Interface 時,如果有多個同名的函數或變數時,應該如何處理 ?

例如 Runnable 和 AnotherRun 這兩個界面都定義了變數 PERIOD 和方法 run。

相同變數名稱:由於 interface內的變數具有 static 的性質,因此使用這些變數時,必須加上 Interface 的名稱才行,如 Runnable.PERIOD,AnotherRun.PERIOD,因此不會造成任何混淆。

相同函數名稱:如果signature (參數個數,型態以及傳回值型態)完全相同,則 Class 只要實作一次即可,例如 Runnable 和 AnotherRun 均定義 void run(),因此 Class D 只要實作一次就好了。如果同名函數符合 Overloading,把它們分別當成不同的 method 即可。如果參數完全相同,但傳回值不同,則違反了Overloading 的原則,會產生 Compile Error。

                             一個 Class 可實作多個 Interface 

No comments:

Post a Comment

n8n index

 【n8n免費本地端部署】Windows版|程式安裝x指令大補帖  【一鍵安裝 n8n】圖文教學,獲得無限額度自動化工具&限時免費升級企業版功能