.NET之二——抽象類、接口與多態性

一、.net接口

       .NET接口是一個或者多個類的公共契約,包含一組虛方法的抽象類型,其中每一種方法都有其名稱、參數和返回值。接口方法不能包含任何實現——這是接口的主要特徵,CLR允許接口可以包含事件、屬性、索引器、靜態方法、靜態字段、靜態構造函數以及常數。一個類可以實現多個接口,當一個類繼承某個接口時,它不僅要實現該接口定義的所有方法,還要實現該接口從其他接口中繼承的所有方法。其次接口不能實例化。具體的說, 接口具有下列屬性:

1、接口類似於抽象基類,繼承接口的任何非抽象類型都必須實現接口的所有成員。

2、不能直接實例化接口,而是應該通過實現接口的類到接口的轉化的方式賦給接口對象。

3、接口可以包含事件、索引器、方法和屬性。

4、接口不包含方法的實現。

5、類和結構可從多個接口繼承。

6、接口自身可從多個接口繼承。

7、接口不能包含數據(也就是字段),接口只能爲public的,其所有的方法都必須是public並且不能顯示的聲明爲public。

8、接口的實現有顯示和隱式實現的區別,可以參見http://blog.csdn.net/qinhl99/archive/2008/10/13/3068149.aspx

9、可以通過增加接口的方式來實現版本控制。

二、抽象類

        .NET抽象類提供多個派生類共享基類的公共定義,它既可以提供抽象方法,也可以提供非抽象方法。抽象類不能實例化,必須通過繼承由派生類實現其抽象方法,因此對抽象類不能使用new關鍵字,也不能被密封。如果派生類沒有實現所有的抽象方法,則該派生類也必須聲明爲抽象類。另外,實現抽象方法由overriding方法來實現。

三、抽象類與接口的區別及使用場景

        相同:

  都不能被直接實例化,都可以通過繼承實現其抽象方法。

  都是面向抽象編程的技術基礎,實現了諸多的設計模式。

  不同點:

  接口是通過派生類的對象轉化爲接口對象來實現實例化的,而抽象類是通過派生類調用其抽象類的構造方法或者是轉化來實例化抽象方法的。

        接口支持多繼承;抽象類不能實現多繼承,通過抽象類繼承會用掉唯一的類繼承選項。

  接口只能定義抽象規則;抽象類既可以定義規則,還可能提供已實現的成員。

  接口是一組行爲規範;抽象類是一個不完全的類。

  接口可以用於支持回調;抽象類不能實現回調,因爲繼承不支持。

  接口只包含方法、屬性、索引器、事件的簽名,但不能定義字段和包含實現的方法;抽象類可以定義字段、屬性、包含有實現的方法。

        接口的所有方法,在派生類中都必須被全部實現,而抽象的類的抽象方法可以部分被實現,另一部分仍然聲明爲抽象方法。

  接口可以作用於值類型和引用類型;抽象類只能作用於引用類型。例如,Struct就可以繼承接口,而不能繼承類。

  接口是通過添加新的接口來達到擴展的目的,而抽象類可以直接修改其定義來達到擴展的目的。

  規則與場合:

  請記住,面向對象思想的一個最重要的原則就是:面向接口編程。

  藉助接口和抽象類,23個設計模式中的很多思想被巧妙的實現了,我認爲其精髓簡單說來就是:面向抽象編程。

  抽象類應主要用於關係密切的對象,而接口最適合爲不相關的類提供通用功能。

  接口着重於CAN-DO關係類型,而抽象類則偏重於IS-A式的關係;

  接口多定義對象的行爲;抽象類多定義對象的屬性;

  接口定義可以使用public、protected、internal 和private修飾符,但是幾乎所有的接口都定義爲public,原因就不必多說了。

  “接口不變”,是應該考慮的重要因素。所以,在由接口增加擴展時,應該增加新的接口,而不能更改現有接口。

  儘量將接口設計成功能單一的功能塊,以.NET Framework爲例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一個公共方法。

  接口名稱前面的大寫字母“I”是一個約定,正如字段名以下劃線開頭一樣,請堅持這些原則。

  在接口中,所有的方法都默認爲public。

  如果預計會出現版本問題,可以創建“抽象類”。例如,創建了狗(Dog)、雞(Chicken)和鴨(Duck),那麼應該考慮抽象出動物(Animal)來應對以後可能出現風馬牛的事情。而向接口中添加新成員則會強制要求修改所有派生類,並重新編譯,所以版本式的問題最好以抽象類來實現。

  從抽象類派生的非抽象類必須包括繼承的所有抽象方法和抽象訪問器的實實現。

  對抽象類不能使用new關鍵字,也不能被密封,原因是抽象類不能被實例化。

  在抽象方法聲明中不能使用 static 或 virtual 修飾符。

  如果預計要創建組件的多個版本,則創建抽象類。抽象類提供簡單易行的方法來控制組件版本。通過更新基類,所有繼承類都隨更改自動更新。另一方面,接口一旦創建就不能更改。如果需要接口的新版本,必須創建一個全新的接口。

  如果創建的功能將在大範圍的全異對象間使用,則使用接口。抽象類應主要用於關係密切的對象,而接口最適合爲不相關的類提供通用功能。

  如果要設計小而簡練的功能塊,則使用接口。如果要設計大的功能單元,則使用抽象類。

  如果要在組件的所有實現間提供通用的已實現功能,則使用抽象類。抽象類允許部分實現類,而接口不包含任何成員的實現。

四、多態性

       

        首先理解一下什麼叫多態。“多態性”是指同一簽名可以有多個實現這一基本的事實。同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果,這就是多態性。多態性通過派生類覆寫基類中的虛函數型方法來實現。多態性分爲兩種,一種是編譯時的多態性,一種是運行時的多態性。

       編譯時的多態性:編譯時的多態性是通過重載來實現的。對於非虛的成員來說,系統在編譯時,根據傳遞的參數、返回的類型等信息決定實現何種操作。

       運行時的多態性:運行時的多態性就是指直到系統運行時,才根據實際情況決定實現何種操作。C#中運行時的多態性是通過覆寫虛成員實現。

        下面我們來分別說明一下多態中涉及到的四個概念:重載,覆寫,虛方法和抽象方法。

        重載和覆蓋的區別:重載——類中定義的方法的不同版本特點:方法名必須相同,參數列表必須不相同,返回值類型可以不相同;覆蓋——子類中爲滿足自己的需要來重複定義某個方法的不同實現, 通過使用override關鍵字來實現覆蓋, 只有虛方法和抽象方法才能被覆蓋 ,覆蓋必須是方法名稱,參數列表,返回值類型都必須相同。注意還可以通過new來重寫或者說隱藏基類的方法或屬性。

       虛方法和抽象方法的區別:

       虛方法,聲明使用virtual關鍵字。調用虛方法,運行時將確定調用對象是什麼類的實例,並調用適當的覆寫的方法。虛方法可以有默認的實現體。
       抽象方法,必須被派生類覆寫的方法。可以看成是沒有實現體的虛方法,如果類中包含抽象方法,那麼類就必須定義爲抽象類,不論是否還包含其他一般方法。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章