CLR不允許繼承多個基類,但是可以繼承多個介面。凡是能使用具名介面類型的執行個體的地方,都能使用實現了介面的一個類型的執行個體。 介面是對一組方法簽名進行了統一命名,但不提供任何實現,而具體類則必須為繼承的全部介面提供實現。
1. 定義介面
介面是用interface關鍵字定義對一組方法簽名,介面名稱一般以字母I開頭;而且還可以為介面定義事件、索引器和屬性,但禁止定義構造器和執行個體欄位,也不能構造任何靜態成員。例如:
public interface IShout
{
public IShout();//×Error Interfaces cannot contain constructors
static void Shout1();//×Error The modifier 'static' is not valid for this item
void Shout();
string Name { get; set; }
}
2. 介面方法
具體的類繼承介面後要為介面中定義的方法提供實現。我們首先定義一個介面,然後再定義類來實現該介面。
public interface IIntroduce
{
void Shout();
void Description();
}
介面方法,即具體類中實現介面中定義的方法,它的實現要注意幾點:
- 介面方法必須是Public;
- CLR要求將介面方法標記為virtual,否則編譯器會自動標籤為virtual和sealed。
public class Animal : IIntroduce
{
public void Shout() //介面方法為標記為virtual
{
Console.WriteLine("Animal Shout.");
}
public virtual void Description() //介面方法標記為virtual
{
Console.WriteLine("Animal Description.");
}
}
查看IL代碼:
- 衍生類別可以使用New關鍵字為介面提供自己的實現。
public class Dog : Animal
{
public override void Description()//重寫基類的介面方法
{
Console.WriteLine("Dog Description!");
}
}
public class Cat : Animal, IIntroduce
{
public override void Description()//重寫基類的介面方法
{
Console.WriteLine("Cat Description!");
}
new public void Shout()//重新實現介面方法
{
Console.WriteLine("Cat Shout.");
}
}
3. 明確介面實作
實現介面有隱式實現和顯式實現兩種方式。當多個介面中包含名稱和簽名都相同的方法時,要使用顯示介面方法實現。
public interface IDemo1
{
void Func();
}
public interface IDemo2
{
void Func();
}
public class Demo : IDemo1, IDemo2
{
public void Func()
{
Console.WriteLine("Demo.Func()");
}
void IDemo1.Func()
{
Console.WriteLine("IDemo1.Func()");
}
void IDemo2.Func()
{
Console.WriteLine("IDemo2.Func()");
}
}
class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
demo.Func();//調用Demo類中的公用方法Func()
((IDemo1)demo).Func(); //顯式調用IDemo1中的Func()
((IDemo2)demo).Func(); //顯式調用IDemo2中的Func()
Console.Read();
}
}
調用結果:
明確介面實作要注意:
- 不允許指定訪問性,如Public等;查看中繼資料時會發現它自動標籤為Private。
- 不能標記為virtual。
- 顯式介面應該謹慎使用,因為實值型別的執行個體在轉型為介面時會發生裝箱,而且顯式介面方法不能被衍生類別繼承。
4.泛型介面
FCL提供了很多現成的介面如IComparable,同時提供了其泛型介面形式IComparable<T>.這樣做能夠編譯時間就檢測類型從而提高了型別安全,而且減少了參數向object類型轉換的裝箱拆箱操作,提高了效能。
int x = 1;
IComparable y = "2";
y.CompareTo(x); //編譯通過,執行階段錯誤
IComparable<int> z = 3;
z.CompareTo(x); //編譯通過,運行通過
5. 基類vs介面
- 如果存在IS-A關係使用基類,存在CAN-DO關係,使用介面。
- 基類實現較容易一些,基類提供的功能衍生類別一般稍作改動即可;而介面方法則要實現所有成員。
- 版本控制:向基類添加新方法後衍生類別可以直接使用;向介面添加新方法後需要修改原始碼並重新編譯。
你也許喜歡:跟小靜讀CLR via C#(00)-開篇及目錄