物件導向-介面
物件導向-介面
介面要求類別實作全部的方法

今天我們有一個外拍任務,需要有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是不是最好了,全都要
別擔心,我們能透過介面來解決這個難題!!!
介面的組成
增加介面跟類別是很像的
- 使用關鍵字不同
- 不能存欄位,但靜態變數是可以的
- public的介面,裡面的任何東西都會自動變成public
- 可以增加方法,不過不能實作
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(); //正確