14 分鐘閱讀

物件導向-介面

介面要求類別實作全部的方法

繼承

今天我們有一個外拍任務,需要有pro或max的相機規格

準備一個使用者的類別

class Phone{
    public Phone(string user){
        User = user;
    }
    public string User;
}
class IPhoneXPro : Phone{
    public IPhoneXPro(string user) : base(user){}

}
class User{
    public void TakePhotoByPro(IPhoneXPro phone){
        DoSomething();
        ''''
        ''''
        ''''
    }
    public void TakePhotoByMax(IPhoneXMax phone){
        DoSomething();
        ''''
        ''''
        ''''
    }
    private void DoSomething(){
        // code
    }

}

拍照要做的事情都一樣,唯一不同就是參數
IPhoneXPro 和 IPhoneXMax
這樣的寫法維護性會很低,兩邊都要改
思考一下,有ProMax是不是最好了,全都要

別擔心,我們能透過介面來解決這個難題!!!

介面的組成

增加介面跟類別是很像的

  1. 使用關鍵字不同
  2. 不能存欄位,但靜態變數是可以的
  3. public的介面,裡面的任何東西都會自動變成public
  4. 可以增加方法,不過不能實作
interface IIPhoneXPro{
  void ProCamera();
}

class User{
    public void TakePhotoByPro(IIPhoneXPro phone){
        DoSomething();
        ''''
        ''''
        ''''
    }
    // code

}

如此,就可以接收有實作IIPhoneXPro的物件作為參數了,很棒
實作IIPhoneXPro這個介面必須有ProCamer的方法

重新思考一次ProMax,我們全都要

class Phone{
    public Phone(string user){
        User = user;
    }
    public string User;
}
interface IIPhoneXPro{
    void ProCamera();
}
interface IIPhoneXMax{
    void MaxCamera();
}
class IPhoneXProMax : Phone, IIPhoneXPro, IIPhoneXMax{
    public IPhoneXProMax(string user) : base(user){}
    public void ProCamera(){
        // code
    }
    public void MaxCamera(){
        // code
    }
}

把本來兩個繼承Phone的子類別IPhoneXPro和IPhoneXMax的類別刪除掉
換成一個類別並且去實作它們的介面

你可能會想說,這樣跟我準備3個類別去繼承Phone有什麼差別
差最多是彈性

類別的繼承負擔比較大,會繼承到方法欄位,而且類別的型態也只有一個

介面的話,跟特別的方法相關,可以不依靠繼承讓某個類別跟相關的方法相關
而且會帶有其介面的類,會有比較多型態

例如,現在的手機可以玩遊戲,以前的人想像的到嗎>今天如果用介面
可以多一個玩遊戲的方法,就可以達成

介面是一個契約

介面裡面的方法沒有實做
當類別去實作介面時(兩個間會有關係)
當類別沒有完全實作介面裡面的方法時,編譯會失敗
當類別確實實作所有的方法時,旅途才可以繼續

介面不可以實例化,但是可以參考它

interface IIPhoneXMax{
    void MaxCamera();
}

IIPhoneXMax phone = new IIPhoneXMax();

去實例化,會發生錯誤

IIPhoneXPro phone = new IPhoneXProMax("Jack");

這一行的意思是
phone 將會指向IPhoneXProMax 所實例化的物件

只要類別有實作某些界面,都可以用這些介面的變數去接收參考

介面可以繼承其他介面

interface IIPhoneXPro{
    void ProCamera();
}
interface IIPhoneXMax{
    void MaxCamera();
}
interface IIPhoneXProMax: IIPhoneXMax, IIPhoneXPro{
    void UltraCamera();
}
class IPhoneXProMax : Phone, IIPhoneXProMax{
  ''''
}

這個時候IPhoneXProMax就不能只有實作UltraCamera方法而已

必須實作ProCamera、MaxCamera、UltraCamera三個方法才是正確的

介面與物件都可以向上轉型與向下轉型

interface Life{
    void Breath();
}
class Human  implements Life{
    public void Breath() {}
    void Walk(){}
}

假設所有生命都會呼吸,人類實作生命,人可以呼吸,自帶一個可以走路的方法
但是不是所有的生命都可以走路

向上轉型意思就是人類->生命 程式碼表示

Human people1 = new Human();

Life people2 = people1;

people2.Breath(); //正確

people2.Walk();  //不正確

向下轉型就是生命->人類

要轉型前可以檢查兩個物件是不是有關係的
向上轉型編譯器都會先檢查,不是相關的類別編譯就會錯誤
向下轉型就是執行階段去檢查了,所以要多多注意

Human NewPeople;
if (people2 instanceof Human){
  NewPeople = (Human) people2;
}
NewPeople.Breath(); //正確

NewPeople.Walk();  //正確

標籤:

更新時間: