【公告】網站目前停止所有的課程訂閱服務,原有學員權益不受影響,造成不便還請見諒,我們正在打造更多課程以及圖書,包含 Python 為主的課程主題,未來將會合併且擴充目前的課程內容,提供全新課程訂閱服務,感謝學員的支持。

介面

介面可以視為只包含抽象成員的一種特殊類別,它只定義成員的介面規格,成員內容則由實作介面的衍生類別根據自身需求提供專屬的實作。介面最大的好處在於將方法成員的規格與實作分開,解決了類別繼承所造成的問題。

繼承機制儘管威力強大,卻相對的衍生出其他的問題,整個繼承關係裏,衍生類別同時被允許存取基礎類別public以及protected層級的相關成員,當繼承架構日益複雜,基礎類別的修改,往往對大量的衍生類別形成不同程度的影響,造成大型系統日後演進的因難,同時降低系統擴充的彈性。

介面將成員規格與實作分開,將類別公用介面從實作中抽離出來,成為獨立不含方法實作的純抽象類別,因此當你定義一個繼承介面的衍生類別,只需遵守方法的宣告語法,再自行定義專屬的方法實作,如此一來即可避免基礎類別與衍生類別之間因為繼承所帶來的問題,另外一方面,由於繼承介面類別可以完全自由實作介面定義的方法內容,在某種程度上亦達到了多型的目的。

接下來從介面的定義開始,討論介面的實作與繼承,說明如何透過介面解決上述繼承所帶來的問題。

定義與使用介面

介面的宣告與類別相當類似,語法如下:

interface Iinterfacename 
{ 
    // interface 規格定義 …
}

關鍵字 interface 表示目前所定義的是一個介面型別,Iinterfacename 則是介面的名稱,大括弧的介面內容包含功能規格定義。

由於介面本身需由外部類別實作其所有方法,因此所有介面方法一律均為 public 層級,不需使用存取修飾詞,當你使用存取修飾詞於方法宣告時,將會產生修飾詞無效的編譯錯誤。

實作介面的類別必須實作其所有方法成員,也就是必須表現介面所有的行為,即使沒有實作其內容,還是必須在實作類別裏,定義介面的方法。



上圖左邊是一個包含兩個方法成員定義的介面 A ,由於這是一個介面,因此其中的方法成員只定義而沒有任何實作內容,右邊則是實作此介面的兩個類別: B 與 C 。

類別 B 在功能面上,只需提供介面 A 方法成員 aMethod 的實作,但是由於其實作了介面,因此必須同時定義 bMethod ,即便只是定義此方法無任何實作內容,類別 C 亦同時實作了介面 A 與其所有成員。來看以下的程式碼,其中建立一個介面型別 IMeasure:

interface IMeasure
{
    void Length();
    void Area();
    void Volume();
}

Length 、 Area 以及Volume 是三個介面方法規格,後續實作此介面的類別必須依據這裏的定義,根據類別的需求,完成三個方法的內容實作。

class Square : IMeasure
{
    public void Length()
    {
        Console.WriteLine("實作Length() 方法");
    }
    public void Area()
    {
        Console.WriteLine("實作Area() 方法");
    }
    public void Volume()
    {
        Console.WriteLine("實作Volume() 方法");
    }
}

類別 Square 實作 IMeasure 介面,此類別實作三個介面定義的方法成員 Length 、Area 以及 Volume,最後建立程式測試類別的功能:

class Program
{
    static void Main(string[] args)
    {
        Square square = new Square();        
        square.Length();
        square.Area();
        square.Volume();
        Console.ReadLine();
    }
}

其中建立 Square 物件實體 square,然後引用實作介面的方法成員,執行程式嗎將會輸出實作的結果。

實作 Length() 方法
實作 Area() 方法
實作 Volume() 方法

此範例說明介面的建立與類別實作,僅輸出提示訊息,並沒有實作真正有意義的內容,方便我們將注意力集中在了解如何使用介面的議題上。

底下列舉幾項介面設計與實作的要點:
  1. 分開方法的定義與實作:介面抽離方法的定義與實作,你可以將其視為一種完全只有抽象方法的純抽象類別。
  2. 避免繼承架構的相依性:介面最大的好處在於避免繼承架構關系裏,基礎類別與衍生類別之間緊密的相依性,提供最大的設計彈性。
  3. 公開所有成員:所有的介面方法成員均只包含方法名稱,且一律為 public 存取層級。
  4. 實作所有介面成員:繼承介面的衍生類別必須實作所有的介面成員,你可以實作一個不包含任何內容的方法,避免編譯錯誤,但是無論如何,衍生類別一定要完成所有的介面方法實作。





沒有留言: