走進C# abstract,瞭解抽象類與介面的異同

追逐時光者發表於2020-11-10

前言:

  最近在研究.NET Core的一些類庫原始碼的時候發現在底層類庫中使用了大量的抽象類,然而發現自己搬磚這麼多年好像從來沒有在專案中使用抽象類或者抽象方法去實現某個功能模組,並且對修飾符Abstract概念也只懂得一些皮毛(也就是面試的時候會問下其基本作用)。當然,我們們不懂就要去慢慢的學習瞭解,不能讓這些不懂的技術和知識點一直困擾著我們。接下來就讓我們一起去探索C# Abstract修飾符的作用,並且瞭解在什麼場景下我們會使用到抽象類,從而提升我們專案的健壯性。

abstract修飾符:

基本概念:abstract修飾符指示要修改的東西有缺失或不完整的實現。

修飾範圍:abstract修飾符可以用於修飾類、方法、屬性、索引器(indexer)和事件。

抽象類:

 public abstract class HttpRequest{}

抽象方法:

//todo:抽象方法不能提供實際的實現,因此沒有方法主體(並且抽象方法只能夠在抽象類中宣告)
public abstract void ActionMethod();

抽象屬性:

public abstract string ContentType { get; set; }

抽象索引器:

public string this[int index] => $"獲取_{index}";

抽象事件:

//首先宣告該事件的委託型別
public delegate void BoilerLogHandler(string status);

// 基於上面的委託定義事件
public abstract event BoilerLogHandler BoilerEventLog;

抽象類與介面的異同:

抽象類的用途:

是一個能夠提供給多個派生類共享的通用基類。

介面的用途:

介面提供了派生類應遵循的標準結構。

抽象類的基本特徵:

1、抽象類是特殊的類,除了不能例項化(只能通過例項化繼承抽象方法的派生類來獲取抽象類中的成員)外,具有類的其他特性(可以單繼承)。
2、抽象類可以定義抽象方法,抽象方法沒有現實。
3、繼承抽象類的類必須把裡面的抽象成員(成員包括:方法,屬性,索引器,事件)全部重寫(orveride),抽象類除外。

介面的基本特徵:

1、介面無法直接進行例項化。

2、一個類或結構可以實現多個介面。

3、實現介面的任何類或結構都必須實現其所有成員。

4、介面包含的成員只有方法,屬性,索引器(有參屬性),事件四種成員。

5、介面不能包含例項欄位、例項建構函式或終結器。 

6、預設情況下,介面成員是公共的,不能有其他的修飾符。

抽象類和介面的區別:

相同:

1、都可以被繼承

2、都不能直接被例項化

3、都可以包含方法宣告且都沒有實現

4、派生類必須實現未實現的成員

不同點:

1、介面可以被多重實現,抽象類只能被單一繼承。

2、介面可以用於支援回撥,繼承並不具備這個特點。

3、抽象類可以定義欄位、方法、屬性、事件、索引器的實現。介面只能定義屬性、索引器、事件、和方法宣告,不能包含欄位。

4、介面中的成員訪問型別預設為公共的,不能有其他的訪問修飾符修飾。

5、定義的關鍵字不一樣,抽象類需要使用abstract,而介面則使用interface。

抽象類和介面的使用:

1、抽象類表共性(常應用在具有相同的行為和特徵中),而介面則表規範(用於定義一種行為)。
2、抽象類主要用於關係密切的物件,而介面最適合為不相關的類提供通用功能。
3、如果要設計大的功能單元,則使用抽象類;如果要設計小而簡練的功能塊,則使用介面。
4、如果預計要建立元件的多個版本,則建立抽象類。介面一旦建立就不能更改。如果需要介面的新版本,必須建立一個全新的介面。
5、如果建立的功能將在大範圍的全異物件間使用,則使用介面;如果要在元件的所有實現間提供通用的已實現功能,則使用抽象類。
6、分析物件,提煉內部共性形成抽象類,用以表示物件本質,即“是什麼”。為外部提供呼叫或功能需要擴充時優先使用介面。
7、好的介面定義應該是具有專一功能性的,而不是多功能的,否則造成介面汙染。如果一個類只是實現了這個介面的中一個功能,而不得不去實現介面中的其他方法,就叫介面汙染。

具體例項如下:

例項一:就像鐵門木門都是門(抽象類),你想要個門我給不了(不能例項化),但我可以給你個具體的鐵門或木門(多型);而且只能是門,你不能說它是窗(單繼承);一個門可以有鎖(介面)也可以有門鈴(多實現)。 門(抽象類)定義了你是什麼,介面(鎖)規定了你能做什麼(一個介面最好只能做一件事,你不能要求鎖也能發出聲音吧(介面汙染))。

例項二:比如說我們一個班級有很多為同學,這些同學都有著各自的特長,愛好,穿衣打扮的風格,因此我們減少程式碼冗餘可以定義一個通用的學生抽象類用來描述學生的身高,體重,姓名,愛好,特徵等相關特徵和行為的公共抽象類。

例項三:我們需要建立 “狗”、“貓”、“魚”、“馬”這些物件(類),我們可以說他們有一些共同的屬性像嘴巴、尾巴、重量、顏色、大小等等一些共同的屬性(properties),但是它們彼此的屬性的形狀是不同的(如嘴巴),在這種情況下,我們如果一個個去定義各自類似的屬性是不是比較繁瑣?如果用抽象類是不是很方便的給他們去繼承。抽象類也有個更加好的地方,體現在“同質異像”就是實質相同實現形式不同的方法繼承上,例如上面的狗、貓、馬等的呼吸這個方法或者跑的速度的方法形式不同,我們這個是用定義一個抽象方法,讓他們各自的類去實現它是不是很方便。“抽象”的意義正在於此。將共同的東西抽出來封裝,但不實現只給繼承。

總結:

  通過對抽象類的深入理解發現原來在程式設計方面需要考慮優化的問題還是有很多很多的,抽象類和介面的選擇就是一個很典型的例子。往往我們會圖簡單而去直接定義介面使用,卻往往忽視了後期的軟體的健壯性和可擴充性。在以後的開發中需要多思考這方面的問題。最後假如文章有什麼需要補充或者不足的地方希望大家指正,謝謝。

參考資料:

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members

https://blog.csdn.net/lizhenxiqnmlgb/article/details/82346478

https://kb.cnblogs.com/page/41836/

 

相關文章