在開發C#的過程中,實現接口時發現有兩個選項,如下圖:
第一個是“隱式實現接口”
第二個是“顯示實現接口”
1、先定義一個接口:
public Interface ICollect
{
string GetName();
}
2、定義一個類,實現上面的接口
public class Api:ICollect
{
/// <summary>
/// 隱式實現接口(我們默認的都是使用隱式的接口)
/// </summary>
public string GetName()
{
return name;
}
}
顯式的實現接口方式:
public class Api:ICollect
{
/// <summary>
/// 顯式實現接口
/// </summary>
public string ICollect.GetName()
{
return name;
}
}
兩者區別:
- 隱式實現接口時,我們有兩種方式調用實現接口的方法(GetName()),即:
ICollect api=new Api();
api.GetName();
和
Api api=new Api();
api.GetName();
- 顯式實現接口時,我們只有一種方法來調用GetName(),即:
ICollect api=new Api();
api.GetName();
最終結論:
1. 隱式實現接口時,接口和類(實現接口的類)都可以訪問類中的方法;
2. 顯式實現接口時,只有通過接口來訪問類中的方法;
顯式優點:
隱藏了實現接口的類的實現代碼
擴展知識:在項目開發時,爲什麼要先寫接口,再寫實現類?
分別定義接口和實現類是架構思想中的開閉原則(擴展開發,修改關閉)的體現,例如:
假如你這個註冊剛開始是對國內用戶開放,中國用戶註冊成功返回“註冊成功”,隨着業務擴展,需要海外用戶開放,假如美國用戶返回“register success”,如果你有接口,可以在美國的AmericaUserServiceImpl.java中實現一個UserService.java的接口,來定義美國用戶的註冊業務,而不是在之UserServiceImpl.java中增加if else來對不同邏輯進行處理,這樣,後續如果某個地區的註冊業務有變動,只需要修改對應地區的實現類,修改不會影響到其他地區的實現類,降低了耦合性。
1、接口的意義在於 抽象、不拘細節,從而使同類事物在同一高度具有通用及可替代性。
2、在系統分析和架構中,分清層次和依賴關係,每個層次不是直接向其上層提供服務(即不是直接實例化在上層中),而是通過定義一組接口,僅向上層暴露其接口功能,上層對於下層僅僅是接口依賴,而不依賴具體類。
接口和抽象類有什麼不同?
下面以C#語言爲示例來講,java也是類似的。
1 相同點
- 都可以被繼承
- 都不能被實例化
- 都可以包含方法聲明
- 派生類必須實現未實現的方法
2 區別
- 語法上
接口 | 抽象類 |
---|---|
接口只能定義屬性、索引器、事件、和方法聲明,沒有普通成員變量 | 抽象類沒有此限制 |
接口不能有構造方法(這簡直是廢話) | 抽象類可以有構造方法 |
接口中的所有方法必須都是抽象的 | 抽象類中可以包含非抽象的普通方法 |
接口中的方法只能是public類型的(默認) | 抽象類中的抽象方法的訪問類型可以是public,protected |
接口可以用於支持回調 | 而繼承並不具備這個特點 |
實現接口的類中的接口方法卻默認爲非虛的,(實現類的派生類,不可以再重寫實現類接口方法,但派生類可以再顯示實現接口的方法) 實現接口的類中的接口方法可以聲明爲virtual(這樣實現類的派生類還可以重寫該方法). |
抽象類實現的具體方法默認爲虛的 |
- 其他方面
接口 | 抽象類 |
---|---|
接口是一個行爲規範 | 抽象類是一個不完整的類,需要進一步細化 |
接口可以被多重實現 | 抽象類只能被單一繼承 |
接口大多數是關係疏鬆但都實現某一功能的類中 | 抽象類更多的是定義在一系列緊密相關的類間 |
接口是爲了滿足外部調用而定義的一個功能約定, 因此反映的是事物的外部特性 | 抽象類是從一系列相關對象中抽象出來的概念, 因此反映的是事物的內部共性 |