本文系原創
抽象類與接口
抽象類和接口有很多相類似的用法,甚至在某些時候可以相互替換使用,很容易搞混淆,所以在進行抽象類定義時對於abstract class和interface的選擇時就比較隨意。其實無論是從使用方法還是在設計思想方案來看,二者的區別還是很大的。
先來看看什么是abstract class,C#允許把類和方法聲明為abstract,即抽象類和抽象方法。
abstract class通常代表一個抽象概念,提供一個繼承的出發點。
在面向對象的概念中,我們知道所有對象都是通過類來描繪的,但是反過來卻不一定是這樣,並不是所有的類都是用來描繪對象的,如果一個類中沒有包含了足夠的信息來描繪一個具體的對象,這樣的類就是abstract class。abstract class往往用來表達一個我們在對問題領域進行分析、設計中得出的一個抽象概念,是對一些看上去不同但是本質上相同的具體概念的抽象。
比如我們在開一個動物園管理系統時,動物園里動物有猴子、老虎、大象等這樣一些具體的對象,猴子、老虎、大象都可以統稱為動物,動物就是這樣的一個抽象的概念,如果描述一個老虎長什么樣子我們都是可以做的到的,如果描述一個動物長什么樣子呢,相信誰都做不到,因為現實中不存在這樣一個對象。
再看interface,interface是把隱式公共方法和屬性組合起來,以封裝特定功能的一個集合,一旦實現了interface,類就可以支持interface所指定的所有屬性和成員。上面我們先從概念上理解了abstract class和interface,下面我們用一個demo來說明abstract class和interface在使用上的一些特點,在c#中定義抽象類如下:
public abstract class Animal
{
public abstract String GetSountSound();
}
定義接口如下:
public interface IAnimal
{
String GetSountSound();
}
在abstract class的方式中,Animal可以有自己的數據成員,也可以有非抽象的成員方法,而在interface的實現方式中,IAnimal中只能有靜態的不能被修改的數據成員,不過在interface中一般不定義數據成員,所有的成員方法都是不包含方法體的。雖然從編程的角度來看,abstract class和interface都可以用來實現面向抽象編程的思想,但是在具體使用上還是有一些區別的。
abstract class在C#中是一個類,是用來被繼承的,一個類只能使用一次幾成關系;但是一個類可以實現多個interface。其次在abstract class在中是可以有非抽象方法的,而在interface的定義中,所有方法都必須是抽象的,也就是沒有方法體的。上面從語法定義和編程的角度我們論述了abstract class在和interface的區別,下面我們從設計理念的層面上分析一下二者的本質區別。前面提到過,abstract class在是被用來繼承的,要想使集成關系合理,父類和子類之間必須存在“is a”的關系,即父類和派生類在概念本質上是相同的,對於interface來說則不然,並不要求interface的實現者和interface定義上在概念本質上是一致的,僅僅是實現了interface定義的契約而已。
也就是說:類是對對象的抽象,abstract class在是對類的抽象,interface是對行為的抽象;如果行為跨越了不同類的對象,可使用interface,對於一些相似的類對象,用繼承abstract class在;從設計角度講,abstract class在是從子類中發現了公共的東西,泛化出父類,然后子類繼承父類,而interface是根本不知道子類的存在,方法如何實現還不確定,預先定義。
總結幾句話來說:
1、abstract class在和interface都不能直接實例化,如果要實例化,abstract class在變量必須指向實現所有抽象方法的子類對象,interface變量必須指向實現所有interfacing方法的類對象。
2、abstract class在要被子類繼承,interface要被類實現。
3、interface只能做方法聲明,abstract class在中可以做方法聲明,也可以做方法實現
4、interface里定義的變量只能是公共的靜態的常量,abstract class在中的變量是普通變量。
5、abstract class在里的抽象方法必須全部被子類所實現,如果子類不能全部實現父類抽象方法,那么該子類只能是abstract class在。同樣,一個實現interface的時候,如不能全部實現接口方法,那么該類也只能為abstract class在。
6、抽象方法只能申明,不能實現。abstract void abc();不能寫成abstract void abc(){}。
7、abstract class在里可以沒有抽象方法
8、如果一個類里有抽象方法,那么這個類只能是abstract class在
9、抽象方法要被實現,所以不能是靜態的,也不能是私有的。
10、interface可繼承interface,並可多繼承interface,但類只能單根繼承。
抽象方法與虛方法
抽象方法是只有定義、沒有實際方法體的函數,它只能在抽象函數中出現,並且在子類中必須重寫;虛方法則有自己的函數體,已經提供了函數實現,但是允許在子類中重寫或覆蓋。重寫的子類虛函數就是被覆蓋了。
抽象方法
使用abstract關鍵字 public abstract bool Withdraw(…);
抽象方法是必須被派生類覆寫的方法。
抽象方法是可以看成是沒有實現體的虛方法
如果類中包含抽象方法,那么類就必須定義為抽象類,不論是否還包含其它一般方法。
虛方法
使用virtual關鍵字 public virtual bool Withdraw(…);
調用虛方法,運行時將確定調用對象是什么類的實例,並調用適當的覆寫的方法。
虛方法可以有實現體 若一個實例方法的聲明中含有 virtual 修飾符,則稱該方法為虛擬方法;
一個虛擬方法的實現可以由派生類取代。取代所繼承的虛擬方法的實現的過程稱為重寫該方法;在一個虛擬方法調用中,該調用所涉及的那個實例的運行時類型確定了要被調用的究竟是該方法的哪一個實現。