重新認識抽象類和接口的區(qū)別
因為平時項目中用到的很少,這種基礎(chǔ)的問題,看了忘,忘了看。從網(wǎng)上找到的千篇一律。今天自己試驗一下這些說法。
三、抽象類和接口的區(qū)別:
1.類是對對象的抽象,可以把抽象類理解為把類當作對象,抽象成的類叫做抽象類.而接口只是一個行為的規(guī)范或規(guī)定,微軟的自定義接口總是后帶able字段,證明其是表述一類類“我能做。。。”.抽象類更多的是定義在一系列緊密相關(guān)的類間,而接口大多數(shù)是關(guān)系疏松但都實現(xiàn)某一功能的類中.
2.接口基本上不具備繼承的任何具體特點,它僅僅承諾了能夠調(diào)用的方法;
3.一個類一次可以實現(xiàn)若干個接口,但是只能擴展一個父類
4.接口可以用于支持回調(diào),而繼承并不具備這個特點.
5.抽象類不能被密封。
6.抽象類實現(xiàn)的具體方法默認為虛的,但實現(xiàn)接口的類中的接口方法卻默認為非虛的,當然您也可以聲明為虛的.
7.(接口)與非抽象類類似,抽象類也必須為在該類的基類列表中列出的接口的所有成員提供它自己的實現(xiàn)。但是,允許抽象類將接口方法映射到抽象方法上。
8.抽象類實現(xiàn)了oop中的一個原則,把可變的與不可變的分離。抽象類和接口就是定義為不可變的,而把可變的座位子類去實現(xiàn)。
9.好的接口定義應(yīng)該是具有專一功能性的,而不是多功能的,否則造成接口污染。如果一個類只是實現(xiàn)了這個接口的中一個功能,而不得不去實現(xiàn)接口中的其他方法,就叫接口污染。
10.盡量避免使用繼承來實現(xiàn)組建功能,而是使用黑箱復(fù)用,即對象組合。因為繼承的層次增多,造成最直接的后果就是當你調(diào)用這個類群中某一類,就必須把他們?nèi)考虞d到棧中!后果可想而知.(結(jié)合堆棧原理理解)。同時,有心的朋友可以留意到微軟在構(gòu)建一個類時,很多時候用到了對象組合的方法。比如asp.net中,Page類,有Server Request等屬性,但其實他們都是某個類的對象。使用Page類的這個對象來調(diào)用另外的類的方法和屬性,這個是非常基本的一個設(shè)計原則。
11.如果抽象類實現(xiàn)接口,則可以把接口中方法映射到抽象類中作為抽象方法而不必實現(xiàn),而在抽象類的子類中實現(xiàn)接口中方法.
第一條:簡單點說就是抽象類是對類的抽象,接口是一個行為的規(guī)范,其他的就太XX了看不懂。
第二條:可以理解為繼承接口只是為了使用接口中的方法
第三條:類可以繼承自多個接口,只能繼承一個類,接口也可以繼承自多個接口啊,區(qū)別就是接口能不能繼承自類了,寫一個接口讓他繼承一個類。
{
}
程序報錯:
![]()
在寫一個抽象類讓他繼承接口和類是不會報錯的。
第四條:意思就是接口可以支持回調(diào),但是抽象類不支持回調(diào)。總網(wǎng)上找了個例子來試試。
代碼
{
public static void CallBackFunction()
{
//傳遞對象給接口類型變量(IBack)
Controller obj = new Controller(new CallBack());
//調(diào)用對象方法
obj.Start();
}
}
public interface IBack
{
void Run();
}
public class CallBack : IBack
{
#region IBack Members
public void Run()
{
Console.WriteLine(DateTime.Now);
}
#endregion
}
public class Controller
{
public IBack CallBackObj = null;
public Controller(IBack obj)
{
CallBackObj = obj;
}
public void Start()
{
Console.WriteLine("敲擊鍵盤任意鍵顯示當前時間,直到按Esc退出");
while(Console.ReadKey(true).Key != ConsoleKey.Escape)
{
CallBackObj.Run();
}
}
}
這個例子很簡單的,就是只要不按下ESC鍵,他就一直執(zhí)行輸出當前時間,Controller類的構(gòu)造函數(shù)的參數(shù)是一個接口類型的,當給他傳入一個他的實現(xiàn)類的對象就會調(diào)用這個對象的方法輸出當前時間。
結(jié)果如下:

然后用抽象類來代替這個接口看看能不能實現(xiàn)這個功能:
代碼
2 {
3 public static void CallBackFunction()
4 {
5 //傳遞對象給接口類型變量(IBack)
6 Controller obj = new Controller(new CallBack());
7 //調(diào)用對象方法
8 obj.Start();
9 }
10 }
11 //public interface IBack
12 //{
13 // void Run();
14 //}
15 //public class CallBack : IBack
16 //{
17
18 // #region IBack Members
19
20 // public void Run()
21 // {
22 // Console.WriteLine(DateTime.Now);
23 // }
24
25 // #endregion
26 //}
27 public abstract class IBack
28 {
29 public abstract void Run();
30 }
31 public class CallBack : IBack
32 {
33 public override void Run()
34 {
35 Console.WriteLine(DateTime.Now);
36 }
37 }
38 public class Controller
39 {
40 public IBack CallBackObj = null;
41 public Controller(IBack obj)
42 {
43 CallBackObj = obj;
44 }
45
46 public void Start()
47 {
48 Console.WriteLine("敲擊鍵盤任意鍵顯示當前時間,直到按Esc退出");
49 while(Console.ReadKey(true).Key != ConsoleKey.Escape)
50 {
51 CallBackObj.Run();
52 }
53 }
54 }
現(xiàn)在讓Controller的構(gòu)造方法接受一個IBack類型的變量,一樣可以實現(xiàn)的。這條區(qū)別有點牽強。
第五條:抽象類不能被密封,意思就是說抽象類不能被密封,接口可以被密封。密封之后就不能被繼承了,所以只要用出現(xiàn):來繼承就會報錯。應(yīng)該也會出現(xiàn)這樣的錯誤的,接口也不能被密封。這條也說不過去。
寫一個語句:
public sealed abstract class IBack{} 報錯
意思很明顯了就是說IBack這個抽象類不能被密封或是靜態(tài)的。
吧sealed用在接口上public sealed interface IBack{}報錯:
意思是關(guān)鍵字sealed不可以用在接口上,這里用item這個詞,也就是說接口相當于一個變量。
兩種都會報錯啊,這條區(qū)別也有點牽強啊。
第六條:抽象類實現(xiàn)的具體方法默認為虛的,但實現(xiàn)接口的類中的接口方法卻默認為非虛的。
抽象類中的方法是虛擬的,但是不提供virtual關(guān)鍵字來修飾,如果寫上了會報錯,接口中的方法是公共的不能申明為虛擬的。這條很明顯。代碼如下:
2 {
3 virtual void Run();
4 }
報錯如下:![]()
將抽象類中的方法表示為虛擬的也會報錯。
{
public virtual abstract void Run();
}
第八條:抽象類實現(xiàn)了oop中的一個原則,把可變的與不可變的分離。抽象類和接口就是定義為不可變的,而把可變的座位子類去實現(xiàn)。這條說的也是相同點嘛,不是區(qū)別。
第九條:好的接口定義應(yīng)該是具有專一功能性的,而不是多功能的,否則造成接口污染。如果一個類只是實現(xiàn)了這個接口的中一個功能,而不得不去實現(xiàn)接口中的其他方法,就叫接口污染。更談不上區(qū)別了。
第十條:盡量避免使用繼承來實現(xiàn)組建功能,而是使用黑箱復(fù)用,即對象組合。因為繼承的層次增多,造成最直接的后果就是當你調(diào)用這個類群中某一類,就必須把他們?nèi)考虞d到棧中!后果可想而知.(結(jié)合堆棧原理理解)。同時,有心的朋友可以留意到微軟在構(gòu)建一個類時,很多時候用到了對象組合的方法。比如asp.net中,Page類,有Server Request等屬性,但其實他們都是某個類的對象。使用Page類的這個對象來調(diào)用另外的類的方法和屬性,這個是非常基本的一個設(shè)計原則。說的是使用組合對象避免多重繼承,這也不是區(qū)別啊。
第十一條:和第七條的后半句雷同的,抽象類可以實現(xiàn)接口,但是不是具體實現(xiàn),而是在他的子類中實現(xiàn)。這也不是區(qū)別。
對于接口和抽象類的區(qū)別,哪位大俠能夠給點經(jīng)典的,經(jīng)得起推敲的答案啊,還有什么時候要用抽象類?什么時候要用接口?
作者:Tyler Ning
出處:http://www.rzrgm.cn/tylerdonet/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,如有問題,請微信聯(lián)系冬天里的一把火

浙公網(wǎng)安備 33010602011771號