介面的出現,是為瞭解決C#中不允許多重繼承的問題。 1、什麼是介面? 我覺得可以把介面理解為對一組方法聲明進行的統一命名,但這些方法沒有提供任何實現。 通過介面,就可以對方法進行統一管理,避免了在每種類型中重覆定義這些方法。 2、如何使用介面來編程 2.1 介面的定義 interface ICust ...
介面的出現,是為瞭解決C#中不允許多重繼承的問題。
1、什麼是介面?
我覺得可以把介面理解為對一組方法聲明進行的統一命名,但這些方法沒有提供任何實現。
通過介面,就可以對方法進行統一管理,避免了在每種類型中重覆定義這些方法。
2、如何使用介面來編程
2.1 介面的定義
interface ICustomCompare
{
//定義比較方法,繼承該介面的類都要實現該方法
int CompareTo(object other);
}
在介面中定義方法不能添加任何訪問修飾符,因為介面中的方法預設是public,如果顯示地指定了修飾符,則會出現編譯時錯誤。也不能使用static關鍵字進行修飾。
在介面中除了可以定義方法外,還可以包含屬性、事件、索引器,或者這4類成員(包括方法)類型的任意組合;但介面類型不能包含欄位、運算符重載、實例構造函數和析構函數。
2.2 繼承介面
public class Person:ICustomCompare
{
int age;
public int Age{get{return age;} set{age=value;}}
//實現介面方法
public int CompareTo(object value)
{
if(value==null)
{
return 1;
}
//將Object類型強制轉換為Person類型
Person otherp=(Person)value;
//把當前對象的Age屬性與需要比較的對象的Age屬性進行對比
if(this.Age<otherp.Age)
{
return -1;
}
if(this.Age>otherp.Age)
{
return 1;
}
return 0;
}
}
在上面的的Person類中,實現了ICustomCompare介面中的CompareTo方法。
CompareTo方法會首先判斷參數對象是否為null,如果為null,則直接返回1,代表當前對象比傳入對象大。
如果對象不為空的話,強制轉換成Person類型,對Age屬性進行對比,當前對象的Age屬性值比傳入對象的Age屬性值大,則返回1,如果返回-1,則說明當前對象的Age屬性比傳入的對象小。
2.3 調用介面中的方法
class Program
{
static void Main(string[] args)
{
Person p1=new Person();
p1.Age=18;
Person p2=new Person();
p2.Age=19;
//調用介面中方法,對p1和p2進行比較
if(p1.CompareTo(p2)>0)
{
Console.WriteLine("p1比p2大");
}
else if(p1.CompareTo(p2)<0)
{
Console.WriteLine("p1比p2小");
}
else
{
Console.WriteLine("p1比p2一樣大");
}
Console.ReadKey();
}
}
3、顯示介面實現方法
在上面的示例代碼當中,使用了隱式的介面實現方式,即在實現代碼中沒有指定實現哪個介面中的CompareTo方法。
當然,也存在顯式的介面實現方式,在類實現介面的過程中,明確指出實現哪一個介面中的哪一個方法。
interface IChineseGreeting
{
//方法聲明
void SayHello();
}
interface IAmericanGreeting
{
//方法聲明
void SayHello();
}
//Speaker類實現了兩個介面
public class Speaker:IChineseGreeting,IAmericanGreeting
{
//隱式介面實現
public void SayHello()
{
Console.WriteLine("你好");
}
}
上面的Speaker類實現了兩個介面,碰巧兩個介面中聲明的方法具有相同的返回類型、相同的方法名稱和相同的參數。若採用隱式的介面實現方式,下麵的代碼將調用相同的SayHello方法。
static void Main(string[] args)
{
Speaker speaker=new Speaker();
//調用中國人打招呼方法
IChineseGreeting chinese=(IChineseGreeting)speaker;
chinese.SayHello();
//調用美國人招呼方法
IAmericanGreeting American=(IAmericanGreeting)speaker;
American.SayHello();
}
當Main函數執行的時候,得到的介面是兩個 “你好”;
這並不是我們期望的結果,所以這種情況下,我們必須使用顯式的介面實現方式來解決這個命名衝突問題。
//Speaker類實現了兩個介面
public class Speaker:IChineseGreeting,IAmericanGreeting
{
//顯式介面實現
void IChineseGreeting.SayHello()
{
Console.WriteLine("你好");
}
//顯式介面實現
void IAmericanGreeting.SayHello()
{
Console.WriteLine("Hello");
}
}
使用這種方式就可以解決命名衝突問題。在使用顯示的介面山西ian方式時,需要註意一下幾個問題:
- 若顯式實現介面,方法不能使用任何訪問修飾符,顯式實現的成員都預設為私有。
- 顯式實現的成員預設是私有的,所以這些成員都不能通過類的對象進行訪問。正確的調用方法是把speaker對象顯式地轉換成對應的介面,通過介面來調用SayHello方法。
針對以上的兩種方式:顯式實現和隱式實現,下麵針對兩種實現的區別和使用場景進行總結:
- 採用隱式介面實現時,類和介面都可以訪問介面中的方法;而若採用顯式介面實現方式,介面方法只能通過介面來完成訪問,因此此時介面方法預設為私有。
- 當類實現單個介面時,通常使用隱式介面實現方式,這樣類的對象可以直接去訪問介面方法。
- 當類實現了多個介面,並且介面中包含相同的方法名稱、參數和返回類型時,則應使用顯式介面實現方式。即使沒有相同的方法簽名,在實現多個介面時,扔推薦使用顯式的 方法,因為這樣可以標識出哪個方法屬於哪個介面。
4、介面與抽象類
這裡主要是闡述一下兩者的區別:
- 抽象類使用abstract關鍵字進行定義,而介面使用interface進行定義;他們都不能進行實例化。
- 抽象類中可以包含虛方法、非抽象方法和靜態成員;但介面中不能包含虛方法和任何靜態成員,並且介面中只能定義方法,不能有具體實現,方法的具體實現由實現類完成。
- 抽象類不能實現多繼承,介面則支持多繼承。註意,從嚴格意義上說,類接觸介面應該成為類實現介面。
- 抽象類是對一類對象的抽象,繼承於抽象類的類與抽象類為屬於的關係;而類實現介面只是代表實現類具有介面聲明的方法,是一種Can-DO的關係。所以一般介面後都帶有able欄位,表示“我能做”的意思。
上面的幾點只是介面與抽象類之間差異的主要方法,它們還有很多的不同,大家可以參考一下別的書籍或者別的博客。