C#中的抽象類別與介面的詳解

黄舟
發布: 2017-09-25 11:15:32
原創
2610 人瀏覽過

問題出現:

我們在使用C#的抽象類別和介面的時候,往往會遇到以下類似的問題,大致歸納如下:

( 1)抽象類別和介面有什麼本質的差別和連結?

(2)什麼時候選擇使用抽象類,但時候使用介面最恰當呢?

(3)在專案中怎麼使用才能讓專案更有可維護性、擴充性?怎樣將它和Struct,類緊密的結合,達到最終的雙面刃作用?

解決方案:

這也是我在學習抽象類別和介面的時候遇到的問題,從我歸納的這三個問題,不難看出這也許是我們大多數程式設計師遇到問題的三個階段,

#第一階段(基礎概念):就像問題1一樣,這部分人首先需要掃清基礎概念的障礙,首先得懂得什麼叫抽象類,什麼叫接口?

然後了解抽象類別和介面之間的差異和聯繫是什麼?當然這可能需要一段時間去理解和實踐,畢竟這些概念比較抽象,屬於那種摸不著看不到的東西,當然最主要還是多練習,沒事的時候做個Demo實例,把它們都使用一遍,在使用的過程中多想想為什麼要這樣用?這用有什麼好處?能不能使用介面呢,如果不能,使用抽象類別好處又在哪?這樣可以加深對它們的理解,這也是我的一點經驗吧,呵呵!說了這麼多,我還是把問題1總結一下,一是方便自己記,二是加深理解吧。

抽象類別和介面的概念:其實這些概念在教科書和部落格基本上一大堆,前輩們總結的也很好了,但是可能在通俗、易懂方面有點晦澀難懂,我就翻譯一下,加點陝西版的白話文,嘿嘿。

(1)抽象類別:提供了一組衍生類別存取共享基底類別的公共方法;

抽象類別的特性是:(1)抽象類別既包括抽象方法,也可以包括方法的實作;(2)抽象類別不能被實例化,也不能被密封;(3)抽象類別中的抽象方法要麼在衍生類別中實現,要麼用派生抽象類別繼承(抽象衍生類別可以繼承基底類別抽象方法的),如果要在衍生類別中實作基底類別的抽象方法,必須使用override 修飾符;(4)抽象類別屬於單一繼承(這點屬於所有類別的同性,在這提一下)(5)抽象類別是一族群的抽象,類似IS-A;

以上我如果說的還不是很清楚,給你個官網的關於抽象類別的位址:https://docs.microsoft.com/ en-us/dotnet/csharp/language-reference/keywords/abstract

(2)介面:包含了一組虛擬方法的抽象類型;

介面的特性是:(1)介面中只包括虛擬方法的定義,只有聲明定義,沒有函數實作;(2)介面類別中可以包括屬性、事件、索引器等,但不能包含欄位;(3)介面類別屬於多重繼承;(4)繼承了介面的類別必須全部實作介面的方法;

抽象類別和介面的區別和聯繫:

相同點:(1)都是不能直接實例化,只能透過繼承方式去實現;

(2)都是對事物行為和物件的抽象,形成一定的設計模式;

不同點:

(1)介面支援多重繼承;抽象類別不能實現多重繼承;

(2)介麵包括方法、屬性、事件、索引器,不能包括欄位;抽象類別可以包括字段,也可以包括方法的實作;

(3)介面可以支援回調,抽象類別不支援回呼

(4)介面可以作為值類型和引用型別基類,而抽象類別只能作為引用型別的基底類;

第二階段(使用階段):就像問題2一樣,這部分人對基礎有了一定的了解,但就是缺乏一定的實踐,或許就是做個簡單的Demo了事,那麼什麼時候用抽象類,啥時用介面呢?

分析第二個問題,我提出3點建議:

第一個建議,對基礎概念不只是概念的記憶,要多練、多思,然後再多練、再多思,循環幾次,直到熟爛於心;

第二個建議,盡量在自己的專案中使用這方面的知識,去使用它,你才能發現問題,解決問題,才會思考;

第三個建議,對自己使用過的抽象類別和接口的項目的知識點進行總結和歸納;
      就什麼時候使用抽象類別和接口,我總結前輩的經驗,給以下幾點,僅供參考:

(1)當設計的元件將來有多個版本的時候一般使用抽象類,例如用C#設計資料庫DB,剛開始你可能使用的是sql server ,mysql,以後大型的專案可能要使用oracle, DB這個大型的資料庫系統,那麼我們在設計類別的時候就設計一個抽象的基底類別DB,讓它有                      資料的一些通用的屬性和方法,屬性:資料庫的連接名,版本,資料庫類型,資料庫的通用方法:Open(),Close()方法等;

(2)當設計的組件同時支援通用的行為動作,可以考慮介面;例如鳥類,人類,車類都可以有聲音,這時候可以設計接口,包含叫的函數行為,然後在各個具體的類別中實現;

(3)在繼承了接口的派生類或接口中,一旦該接口需要增加行為方法是個比較頭痛的事情,必須所有的繼承都必須實現它的方法,這個時候可以在派生類去實現一個新增的接口,來實現派生類的獨特動作,舉例說明:

/// <summary>
/// 实现一个爬行动物的动作接口
/// </summary>
interface IAnimalClimb
{
void Climb();
}
/// <summary>
/// 实现一个会叫的动物的动作接口
/// </summary>
interface ICry
{
void Cry();
}
/// <summary>
/// 实现一个动物抽象类
/// </summary>
public abstract class Animal
{
//动物的名字
public string Name { get; set; }
//动物的颜色
public string Color { get; set; }
//动物抽象类的共有方法
public abstract void Sleep();
public abstract void Breathe();
}
/// <summary>
/// 定义鸟类,通用方法是会飞
/// </summary>
public class Bird : Animal,ICry
{
public override void Sleep()
{
Console.WriteLine("Bird派生类继承了基类的Sleep()方法");
}
public override void Breathe()
{
Console.WriteLine("Bird派生类继承了基类的Breathe()方法");
}
//鸟类可以继承统一的接口动作,例如:叫
public void Cry()
{
Console.WriteLine("Bird派生类继承了接口ICry的叫的方法");
}
}
/// <summary>
/// 定义爬行动物类
/// </summary>
public class Snake : Animal, IAnimalClimb
{
public override void Breathe()
{
Console.WriteLine("Snake派生类继承了基类的Sleep()方法");
}
public override void Sleep()
{
Console.WriteLine("Snake派生类继承了基类的Sleep()方法");
}
//爬行动物可以继承统一的接口动物,例如:爬
public void Climb()
{
Console.WriteLine("Snake派生类继承了接口IAnimalClimb的爬的方法");
}
}
登入後複製

以上程式碼,只是說明問題,比較簡單;
第三階段(優化階段):就像問題3一樣,我們在做一個抽象類別或介面的時候首先考慮的是能用就行,結果就是定義的類或介面比較多,難以維護和擴展,或是類別之間有交集,那怎麼優化繼承關係?怎麼樣才能使得程式具有可維護性和擴充性?
我個人建議具備以下幾個面向方可:
(1)要有紮實的基礎知識和深厚的基礎功底;
(2)要有一個多問、多思的心;對於抽象類別和介面多問,為什麼不使用抽象類別而要使用介面?為什麼在這個地方使用介面合適?
(3)多看看前輩們是怎麼設計介面和類別的,這方面的資料網上搜搜不少;
(4)個人建議多看看設計模式這方面的知識,因為他們是前輩設計時的經驗與想法; 

以上是C#中的抽象類別與介面的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!