小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

C#中的interface沒那么簡單

 戴維圖書館 2017-08-29

最近在園子里閑逛看到一篇文章“(抽象)類和接口細(xì)節(jié)分析”,盡管作者很細(xì)心很細(xì)致??墒聦嵣螩#里面的interface沒那么簡單,interface有著大量不為人知的小秘密的說。

 

1、值類型也能實現(xiàn)接口。

盡管可能很多人連值類型都沒用過,但值類型可以實現(xiàn)接口,是一個非常有用的特性。當(dāng)值類型轉(zhuǎn)換為接口類型時,會自動裝箱成引用類型從而實現(xiàn)多態(tài),但一般用值類型實現(xiàn)接口的老鳥都不會被這些小陷阱所迷惑的。

 

2、除了接口,沒有什么類型可以不實現(xiàn)接口

抽象類可以不實現(xiàn)接口?其實不然,抽象類只能抽象接口的實現(xiàn),即將實現(xiàn)變?yōu)閍bstract的,但不能不實現(xiàn)接口。也許你會疑惑,abstract實現(xiàn)接口成員和不實現(xiàn)接口成員到底有區(qū)別?盡管區(qū)別不大,但還是存在的,從理論上來說的話,就是slot上的方法的區(qū)別。抽象類用abstract成員實現(xiàn)接口后,子類再override來實現(xiàn)抽象類的abstract成員,這會使得子類的實現(xiàn)是在abstract實現(xiàn)之下而不是直接在接口成員之下。從實際效果上來說,由于抽象類的abstract的實現(xiàn)存在,使得子類中可以選擇對抽象類和接口進(jìn)行分別實現(xiàn)(重新實現(xiàn)接口)。

 

3、但事實上接口也不能實現(xiàn)接口,只是把多個接口捆綁起來。

一段有趣的代碼如下

public interface IA
{
  void Test();
}

public interface IB : IA { }

public interface IC : IA { }

public interface ID : IB, IC { }

當(dāng)實現(xiàn)ID時,等于同時實現(xiàn)ID、IC、IB和IA,但事實上,你只需要實現(xiàn)一個Test方法,也只能實現(xiàn)一個Test方法,也就是IA.Test,IB、IC、ID都是沒有Test方法的。

當(dāng)然,你可以嘗試在IB或是其他接口中再放入一個Test,便會產(chǎn)生一些奇妙的事情。

 

4、同一接口成員在同一類型中只能被實現(xiàn)一次。

顯示實現(xiàn)接口已經(jīng)不是什么秘密了,但很多人卻并不知道,如果你顯示實現(xiàn)了接口,那么隱式實現(xiàn)就不存在了。這就是接口只能被實現(xiàn)一次:

 

public interface IA
{
  void Test();
}

public interface IB
{
  void Test();
}


public class TestClass : IA, IB
{

  public void Test()
  {
    throw new NotImplementedException();
  }

  void IB.Test()
  {
    throw new NotImplementedException();
  }
}

 

在這段代碼中,第一個Test方法實際上只實現(xiàn)了IA.Test,而如果將第二個Test方法去掉,則第一個方法就會同時實現(xiàn)兩個Test,即IA.Test和IB.Test。不妨自己動手去試一下。

 

5、同一個類型也只能實現(xiàn)同一個接口一次。

其實不論類型的父類重復(fù)實現(xiàn)了同一個接口多少次,一個類型只能實現(xiàn)一個接口一次??紤]下面的代碼:

public interface ITest
{
  void Test();
}

public abstract class Test1 : ITest
{
  public void Test()
  {
    throw new NotImplementedException();
  }
}

public abstract class Test2 : Test1, ITest
{
  public new void Test()
  {
    throw new NotImplementedException();
  }
}

public abstract class Test3 : Test2, ITest
{
  public new void Test()
  {
    throw new NotImplementedException();
  }
}

無論在基類中實現(xiàn)了多少次ITest接口,事實上在ITest3的接口列表中永遠(yuǎn)只有一個ITest(GetInterfaces),也只能對ITest的每個成員實現(xiàn)一次(隱式或顯式)。

 

6、實現(xiàn)接口的成員實際可見性總是不低于接口可見性。顯示實現(xiàn)接口的成員可見性總是等同于接口可見性(因為它們默認(rèn)都是private的)。

重寫基類成員的成員必須有相同的可見性,接口則不必,隱式實現(xiàn)總是要求成員必須為public。同時,一個類型可以實現(xiàn)可見性比自己高或低的接口,但不能繼承可見性比自己低的基類。

因為能訪問到接口的類型的地方一定能訪問到接口的實現(xiàn)成員,所以實現(xiàn)接口的成員的實際可見性總不低于接口。

一個很常見的手法,一個可見性較低的類型通過可見性高的接口來暴露自己的成員,事實幾乎所有的枚舉器(IEnumerator的實例)都是private的類型,透過接口來暴露功能。

 

當(dāng)然,你也可以設(shè)計一個internal的接口,然后讓某個類型去“顯示實現(xiàn)”,這個時候?qū)崿F(xiàn)接口的成員的“實際”可見性將跟隨接口變?yōu)閕nternal。

由于隱式實現(xiàn)接口要求成員必須是public的,如果要用可見性較低的接口來制約成員可見性就只能用顯式實現(xiàn)接口成員。也許有人會很奇怪我干嘛降級成員的可見性?因為有時候可見性高了并不是什么好事,它會破壞組件(不是類型)的封裝。當(dāng)然更多的時候,我們只是需要一個手段來統(tǒng)一設(shè)置某些成員的可見性。

 

不過,我們也能想出更多非常好玩的玩法:

public abstract class Test
{
  protected interface ITest
  {
    void Test();
  }

  public class Nested : ITest
  {

    void ITest.Test()
    {
      throw new NotImplementedException();
    }
  }
}

這也是顯示實現(xiàn)接口特性除了解決名稱和沖突問題之外最大的用處。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多