《C#入門詳解》劉老師 抽象類與開閉原則
抽象類&開閉原則
一、概念
為做基類而生的“抽象類”與“開放/關閉原則”
抽象類是函數成員沒有被完全實現的類,就是類里面可以有若干個函數成員,其中至少有一個函數成員沒有被實現。沒有被實現的函數成員一定要用abstract來修飾。不允許實例化一個抽象類。
一個類不能被實例化,就剩兩個用處了。第一,作為基類,在派生類中把沒有實現的函數成員實現。第二,抽象類作為基類去聲明變量,用基類類型的變量去引用子類類型的實例。
子類如果沒有全部實現父類(抽象類)的抽象方法,則該子類依然是抽象類。

二、抽象類與接口
如果單從具體代碼來看,對這兩個概念很容易模糊,甚至覺得接口就是多余的,因為單從具體功能來看,除多重繼承外,抽象類似乎完全能取代接口。但是,難道接口的存在是為了實現多重繼承?當然不是。我認為,抽象類和接口的區別在于使用動機。使用抽象類是為了代碼的復用,而使用接口的動機是為了實現多態性。所以,如果你在為某個地方該使用接口還是抽象類而猶豫不決時,那么可以想想你的動機是什么。
看到有朋友對IVehicle這個接口的質疑,我個人的理解是,IVehicle這個接口該不該定義,關鍵看具體應用中是怎么個情況。如果我們的項目中有Car和Heavy Car,都繼承Vehicle,而且Car和Heavy Car絕大多數方法都相同,只有一個方法Running Speed()不同,那么當然定義一個AbstractVehicle抽象類比較合理,因為它可以把其他所有方法都包含進去,子類只定義Running Speed(),大大減少了重復代碼量。
但是,如果我們程序中的Car 和 Heavy Car兩個類基本沒有共同代碼,而且有一個Run類需要實例化他們,并且不希望知道他們是汽車還是重型卡車,而只需把他們當作車來看待,并實現多態,那么定義成接口就有必要了。
總而言之,接口與抽象類的區別主要在于使用的動機,而不在于其本身。而一個東西該定義成抽象類還是接口,要根據具體環境的上下文決定。
再者,我認為接口和抽象類的另一個區別在于,抽象類和它的子類之間應該是一般和特殊的關系,而接口僅僅是它的子類應該實現的一組規則。(當然,有時也可能存在一般與特殊的關系,但我們使用接口的目的不在這里)如,交通工具定義成抽象類,汽車、飛機、輪船定義成子類,是可以接受的,因為汽車、飛機、輪船都是一種特殊的交通工具。再譬如Icomparable接口,它只是說,實現這個接口的類必須要可以進行比較,這是一條規則。如果Car這個類實現了Icomparable,只是說,我們的Car中有一個方法可以對兩個Car的實例進行比較,可能是比哪輛車更貴,也可能比哪輛車更大,這都無所謂,但我們不能說“汽車是一種特殊的可以比較”,這在文法上都不通。

浙公網安備 33010602011771號