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

來源:互聯網
上載者:User
本文主要介紹了C#中抽象類別與介面的區別。具有很好的參考價值。下面跟著小編一起來看下吧

1.面向介面編程和物件導向編程是什麼關係

首先,面向介面編程和物件導向編程並不是平級的,它並不是比物件導向編程更先進的一種獨立的編程思想,而是附屬於物件導向思想體系,屬於其一部分。或者說,它是物件導向編程體系中的思想精髓之一。

2.介面的本質

介面,在表面上是由幾個沒有主體代碼的方法定義組成的集合體,有唯一的名稱,可以被類或其他介面所實現(或者也可以說繼承)。它在形式上可能是如下的樣子:

interface InterfaceName{ void Method1(); void Method2(int para1); void Method3(string para2,string para3);}

那麼,介面的本質是什麼呢?或者說介面存在的意義是什麼。我認為可以從以下兩個視角考慮:

1)介面是一組規則的集合,它規定了實現本介面的類或介面必須擁有的一組規則。體現了自然界“如果你是……則必須能……”的理念。

例如,在自然界中,人都能吃飯,即“如果你是人,則必須能吃飯”。那麼類比到電腦程式中,就應該有一個IPerson(習慣上,介面名由“I”開頭)介面,並有一個方法叫Eat(),然後我們規定,每一個表示“人”的類,必須實現IPerson介面,這就類比了自然界“如果你是人,則必須能吃飯”這條規則。

從這裡,我想各位也能看到些許物件導向思想的東西。物件導向思想的核心之一,就是類比真實世界,把真實世界中的事物抽象成類,整個程式靠各個類的執行個體互相通訊、互相協作完成系統功能,這非常符合真實世界的健全狀態,也是物件導向思想的精髓。

2)介面是在一定粒度視圖上同類事物的抽象表示。注意這裡我強調了在一定粒度視圖上,因為“同類事物”這個概念是相對的,它因為粒度視圖不同而不同。

例如,在我的眼裡,我是一個人,和一頭豬有本質區別,我可以接受我和我同學是同類這個說法,但絕不能接受我和一頭豬是同類。但是,如果在一個動物學家眼裡,我和豬應該是同類,因為我們都是動物,他可以認為“人”和“豬”都實現了IAnimal這個介面,而他在研究動物行為時,不會把我和豬分開對待,而會從“動物”這個較大的粒度上研究,但他會認為我和一棵樹有本質區別。

現在換了一個遺傳學家,情況又不同了,因為生物都能遺傳,所以在他眼裡,我不僅和豬沒區別,和一隻蚊子、一個細菌、一顆樹、一個蘑菇乃至一個SARS病毒都沒什麼區別,因為他會認為我們都實現了IDescendable這個介面(註:descend vi. 遺傳),即我們都是可遺傳的東西,他不會分別研究我們,而會將所有生物作為同類進行研究,在他眼裡沒有人和病毒之分,只有可遺傳的物質和不可遺傳的物質。但至少,我和一塊石頭還是有區別的。

可不幸的事情發生了,某日,地球上出現了一位偉大的人,他叫列寧,他在熟讀馬克思、恩格斯的辯證唯物主義思想巨著後,頗有心得,於是他下了一個著名的定義:所謂物質,就是能被意識所反映的客觀實在。至此,我和一塊石頭、一絲空氣、一條成語和傳輸手機訊號的電磁場已經沒什麼區別了,因為在列寧的眼裡,我們都是可以被意識所反映的客觀實在。如果列寧是一名程式員,他會這麼說:所謂物質,就是所有同時實現了“IReflectabe”和“IEsse”兩個介面的類所產生的執行個體。(註:reflect v. 反映 esse n. 客觀實在)

也許你會覺得我上面的例子像在瞎掰,但是,這正是介面得以存在的意義。物件導向思想和核心之一叫做多態性,什麼叫多態性?說白了就是在某個粒度視圖層面上對同類事物不加區別的對待而統一處理。而之所以敢這樣做,就是因為有介面的存在。像那個遺傳學家,他明白所有生物都實現了IDescendable介面,那隻要是生物,一定有Descend()這個方法,於是他就可以統一研究,而不至於分別研究每一種生物而最終累死。

可能這裡還不能給你一個關於介面本質和作用的直觀印象。那麼在後文的例子和對幾個設計模式的解析中,你將會更直觀體驗到介面的內涵。

3.面向介面編程綜述

那麼什麼是面向介面編程呢?我個人的定義是:在系統分析和架構中,分清層次和依賴關係,每個層次不是直接向其上層提供服務(即不是直接執行個體化在上層中),而是通過定義一組介面,僅向上層暴露其介面功能,上層對於下層僅僅是介面依賴,而不依賴具體類。

這樣做的好處是顯而易見的,首先對系統靈活性大有好處。當下層需要改變時,只要介面及介面功能不變,則上層不用做任何修改。甚至可以在不改動上層代碼時將下層整個替換掉,就像我們將一個WD的60G硬碟換成一個希捷的160G的硬碟,電腦其他地方不用做任何改動,而是把原硬碟拔下來、新硬碟插上就行了,因為電腦其他部分不依賴具體硬碟,而只依賴一個IDE介面,只要硬碟實現了這個介面,就可以替換上去。從這裡看,程式中的介面和現實中的介面極為相似,所以我一直認為,介面(interface)這個詞用的真是神似!

使用介面的另一個好處就是不同組件或層次的開發人員可以並行開工,就像造硬碟的不用等造CPU的,也不用等造顯示器的,只要介面一致,設計合理,完全可以並行進行開發,從而提高效率。

對本文的補充:

1.關於“面向介面編程”中的“介面”與具體物件導向語言中“介面”兩個詞

看到有朋友提出“面向介面編程”中的“介面”二字應該比單純程式設計語言中的interface範圍更大。我經過思考,覺得很有道理。這裡我寫的確實不太合理。我想,物件導向語言中的“介面”是指具體的一種代碼結構,例如C#中用interface關鍵字定義的介面。而“面向介面編程”中的“介面”可以說是一種從軟體架構的角度、從一個更抽象的層面上指那種用於隱藏具體底層類和實現多態性的結構組件。從這個意義上說,如果定義一個抽象類別,並且目的是為了實現多態,那麼我認為把這個抽象類別也稱為“介面”是合理的。但是用抽象類別實現多態合理不合理?在下面第二條討論。

概括來說,我覺得兩個“介面”的概念既相互區別又相互聯絡。“面向介面編程”中的介面是一種思想層面的用於實現多態性、提高軟體靈活性和可維護性的架構組件,而具體語言中的“介面”是將這種思想中的組件具體實施到代碼裡的手段。

2.關於抽象類別與介面

如果單從具體代碼來看,對這兩個概念很容易模糊,甚至覺得介面就是多餘的,因為單從具體功能來看,除多重繼承外(C#,Java中),抽象類別似乎完全能取代介面。但是,難道介面的存在是為了實現多重繼承?當然不是。我認為,抽象類別和介面的區別在於使用動機。使用抽象類別是為了代碼的複用,而使用介面的動機是為了實現多態性。所以,如果你在為某個地方該使用介面還是抽象類別而猶豫不決時,那麼可以想想你的動機是什麼。

看到有朋友對IPerson這個介面的質疑,我個人的理解是,IPerson這個介面該不該定義,關鍵看具體應用中是怎麼個情況。如果我們的項目中有Women和Man,都繼承Person,而且Women和Man絕大多數方法都相同,只有一個方法DoSomethingInWC()不同(例子比較粗俗,各位見諒),那麼當然定義一個AbstractPerson抽象類別比較合理,因為它可以把其他所有方法都包含進去,子類只定義DoSomethingInWC(),大大減少了重複代碼量。

但是,如果我們程式中的Women和Man兩個類基本沒有共同代碼,而且有一個PersonHandle類需要執行個體化他們,並且不希望知道他們是男是女,而只需把他們當作人看待,並實現多態,那麼定義成介面就有必要了。

總而言之,介面與抽象類別的區別主要在於使用的動機,而不在於其本身。而一個東西該定義成抽象類別還是介面,要根據具體環境的上下文決定。

再者,我認為介面和抽象類別的另一個區別在於,抽象類別和它的子類之間應該是一般和特殊的關係,而介面僅僅是它的子類應該實現的一組規則。(當然,有時也可能存在一般與特殊的關係,但我們使用介面的目的不在這裡)如,交通工具定義成抽象類別,汽車、飛機、輪船定義成子類,是可以接受的,因為汽車、飛機、輪船都是一種特殊的交通工具。再譬如Icomparable介面,它只是說,實現這個介面的類必須要可以進行比較,這是一條規則。如果Car這個類實現了Icomparable,只是說,我們的Car中有一個方法可以對兩個Car的執行個體進行比較,可能是比哪輛車更貴,也可能比哪輛車更大,這都無所謂,但我們不能說“汽車是一種特殊的可以比較”,這在文法上都不通。

C#.NET裡面抽象類別和介面有什麼區別?

介面和抽象類別的概念不一樣。介面是對動作的抽象,抽象類別是對根源的抽象。

抽象類別表示的是,這個對象是什麼。介面表示的是,這個對象能做什麼。比如,男人,女人,這兩個類(如果是類的話……),他們的抽象類別是人。說明,他們都是人。

人可以吃東西,狗也可以吃東西,你可以把“吃東西”定義成一個介面,然後讓這些類去實現它.

所以,在進階語言上,一個類只能繼承一個類(抽象類別)(正如人不可能同時是生物和非生物),但是可以實現多個介面(吃飯介面、走路介面)。

下面接著再說說兩者在應用上的區別:

介面更多的是在系統架構設計方法發揮作用,主要用於定義模組之間的通訊契約。

而抽象類別在代碼實現方面發揮作用,可以實現代碼的重用

模板方法設計模式是抽象類別的一個典型應用

最佳答案:

1抽象類別

(1) 抽象方法只作聲明,而不包含實現,可以看成是沒有實現體的虛方法

(2) 抽象類別不能被執行個體化

(3) 抽象類別可以但不是必須有抽象屬性和抽象方法,但是一旦有了抽象方法,就一定要把這個類聲明為抽象類別

(4) 具體衍生類別必須覆蓋基類的抽象方法

(5) 抽象衍生類別可以覆蓋基類的抽象方法,也可以不覆蓋。如果不覆蓋,則其具體衍生類別必須覆蓋它們。如:

using System;public abstract class A //抽象類別A {  private int num=0; public int Num //抽象類別包含屬性  {   get   {    return num;   }   set   {    num = value;   }    } public virtual int getNum() //抽象類別包含虛方法  {   return num;  } public void setNum(int n) // //抽象類別包含普通方法  {   this.num = n;  } public abstract void E(); //類A中的抽象方法E  }public abstract class B : A //由於類B繼承了類A中的抽象方法E,所以類B也變成了抽象類別 {}public class C : B {  public override void E() //重寫從類A繼承的抽象方法。如果類B自己還定義了抽象方法,也必須重寫  {   //throw new Exception("The method or operation is not implemented.");  } }public class Test {  static void Main()  {   C c = new C();   c.E();  } }

二、接 口

(1) 介面不能被執行個體化

(2) 介面只能包含方法聲明

(3) 介面的成員包括方法、屬性、索引器、事件

(4) 介面中不能包含常量、欄位(域)、建構函式、解構函式、靜態成員。如:

public delegate void EventHandler(object sender, Event e);public interface ITest {  //int x = 0; int A  {   get;   set;  } void Test(); event EventHandler Event;  int this[int index]  {   get;  set;  } }

(5) 介面中的所有成員預設為public,因此介面中不能有private修飾符

(6) 衍生類別必須實現介面的所有成員

(7) 一個類可以直接實現多個介面,介面之間用逗號隔開

(8) 一個介面可以有多個父介面,實現該介面的類必須實現所有父介面中的所有成員

三、抽象類別和介面

相同點:

(1) 都可以被繼承

(2) 都不能被執行個體化

(3) 都可以包含方法聲明

(4) 衍生類別必須實現未實現的方法

區 別:

(1) 抽象基類可以定義欄位、屬性、方法實現。介面只能定義屬性、索引器、事件、和方法聲明,不能包含欄位。

(2) 抽象類別是一個不完整的類,需要進一步細化,而介面是一個行為規範。微軟的自訂介面總是後帶able欄位,證明其是表述一類“我能做。。。”

(3) 介面可以被多重實現,抽象類別只能被單一繼承

(4) 抽象類別更多的是定義在一系列緊密相關的類間,而介面大多數是關係疏鬆但都實現某一功能的類中

(5) 抽象類別是從一系列相關對象中抽象出來的概念, 因此反映的是事物的內部共性;介面是為了滿足外部調用而定義的一個功能約定, 因此反映的是事物的外部特性

(6) 介面基本上不具備繼承的任何具體特點,它僅僅承諾了能夠調用的方法

(7) 介面可以用於支援回調,而繼承並不具備這個特點

(8) 抽象類別實現的具體方法預設為虛的,但實現介面的類中的介面方法卻預設為非虛的,當然您也可以聲明為虛的

(9) 如果抽象類別實現介面,則可以把介面中方法映射到抽象類別中作為抽象方法而不必實現,而在抽象類別的子類中實現介面中方法

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.