跟小靜讀CLR via C#(17)--接口


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代碼:

   clip_image004

clip_image006

 

  • 派生類可以使用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.");
       }
   }

clip_image008

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();
       }
   }

調用結果:

clip_image010

顯式接口實現要注意:

  • 不允許指定訪問性,如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)-開篇及目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM