虛方法、抽象類與抽象方法


抽象類

何時必須聲明一個類為抽象類?(面試題)

當這個類中包含抽象方法時,或是該類並沒有完全實現父類的抽象方法時。

abstract 修飾符可用於類、方法、屬性、索引和事件。 在類聲明中使用 abstract 修飾符以指示某個類僅旨在作為其他類的基類。 標記為 abstract 的成員,或包含在抽象類中的成員,都必須由派生自抽象類的類來實現。

抽象類的特征:

  • 抽象類由abstract關鍵字修飾,只能用作基類
  • 抽象類可能包含抽象方法和訪問器,同時也可以包含非抽象方法和非抽象訪問器(只要有一個抽象方法,該類就必須定義為抽象類)
 1     abstract class AbstractClass
 2     {
 3         public abstract int Age { get; }//抽象訪問器
 4         public string Name { get { return "張三"; } }//非抽象訪問器
 5 
 6         public abstract void AbstractMethod();//抽象方法
 7 
 8         public void Method()//非抽象方法
 9         {
10             Console.WriteLine("抽象類中的非抽象方法");
11         }
12     }
  • 派生自抽象類的非抽象類,必須實現抽象類的所有抽象方法和訪問器,否則該子類也必須聲明為抽象類
 1     class MyClass : AbstractClass
 2     {
 3         //實現抽象類中的抽象訪問器
 4         public override int Age
 5         {
 6             get
 7             {
 8                 return 30;
 9             }
10         }
11         //實現抽象類中的抽象方法
12         public override void AbstractMethod()
13         {
14             Console.WriteLine("在派生類中實現的抽象方法");
15         }
16     }
  • 抽象類不能被實例化(但是抽象類中可以有構造函數),只能通過派生類進行實例化
 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //AbstractClass abstractClass = new AbstractClass();//抽象類不能實例化,這種寫法會報錯
 6             MyClass myclass = new MyClass();
 7             Console.WriteLine(myclass.Age);//30
 8             Console.WriteLine(myclass.Name);//張三
 9             myclass.Method();//抽象類中的非抽象方法
10             myclass.AbstractMethod();//在派生類中實現的抽象方法
11 
12             Console.ReadKey();
13         }
14     }
  • 抽象類不能使用sealed修飾符來修飾,因為abstract和sealed兩個修飾符有相反的含義(sealed表示該類不能被繼承,abstract表示該類可以被繼承)
  • 抽象類可以被抽象類繼承,此時抽象的派僧類可以對抽象基類中的抽象方法進行重寫,也可以不進行重寫,但是必須在該抽象派生類的子類中對其進行重寫

抽象方法和抽象訪問器

  • 抽象方法使用abstract修飾,使用static和virtual修飾是錯誤的
  • 抽象方法是隱式的虛方法
  • 只有抽象類才允許聲明抽象方法
  • 抽象方法只有方法簽名,沒有方法具體實現的方法體
  • 在靜態屬性上是用abstract修飾符是錯誤的
  • 通過override修飾符,可以在派生類中重寫抽象類中的抽象方法和抽象訪問器
  • 抽象成員不能是私有的

虛方法

  • 虛方法使用virtual關鍵字修飾
  • 虛方法不能是私有的
  • virtual修飾符不能與static、abstract、private、override修飾符一起使用
  • 通過override關鍵字對虛方法進行重寫
 1     class Class1
 2     {
 3         public virtual void ShowInfo()
 4         {
 5             Console.WriteLine("虛方法在父類中的實現");
 6         }
 7     }
 8 
 9     class Class2 : Class1
10     {
11         public override void ShowInfo()
12         {
13             Console.WriteLine("虛方法在子類中的實現");
14         }
15     }
16 
17     class Program
18     {
19         static void Main(string[] args)
20         {
21             Class2 c = new Class2();
22             c.ShowInfo();//虛方法在子類中的實現
23 
24             Console.ReadKey();
25         }
26     }

1、當調用一個對象的函數時,系統會先去檢查這個對象所屬的類,看所調用的函數是否為虛函數;

2、如果不是虛函數,那么它就直接執行該函數。而如果有virtual關鍵字,也就是一個虛函數,那么這個時候它就不會立刻執行該函數了,而是轉去檢查對象的實例類。

3、在這個實例類里,他會檢查這個實例類的中是否重寫該虛函數(通過override關鍵字),如果是有,那么就馬上執行該實例類中的這個重新實現的函數;如果沒有的話,系統就會不停地往上找實例類的基類,直到找到第一個重寫了該虛函數的基類為止,然后執行該基類中的函數。

抽象方法與虛方法的區別:

  • 抽象方法必須定義在一個抽象類中,虛方法沒有特殊要求
  • 抽象方法在基類中不可以有具體的實現,而虛方法在基類中必須有具體的實現
  • 抽象方法要求必須在派生類中對其進行重寫;而虛方法可以在派生類中對其進行重寫,也可以不對其進行重寫

抽象類與接口的相同點:

  • 都可以被繼承
  • 都不可以實例化
  • 都可以包含方法聲明
  • 派生類都必須實現其未實現的方法

抽象類與接口的區別:

  • 抽象類可以定義字段、屬性,可以包含方法的實現,可定義的內容與非抽象類基本一致;而接口只能定義屬性、索引器、事件和方法聲明,不能包含字段和方法實現
  • 抽象類是一個不完整的類,需要進一步細化擴展;而接口是一個行為規范
  • 抽象類更多的是定義在一系列緊密相關的類之間;而接口大多數是關系疏松但都實現某一功能的類中
  • 抽象類是從一系列相關對象中抽象出來的概念, 因此反映的是事物的內部共性;接口是為了滿足外部調用而定義的一個功能約定, 因此反映的是事物的外部特性
  • 接口基本上不具備繼承的任何具體特點,它僅僅承諾了能夠調用的方法
  • 可以用於支持回調,而繼承並不具備這個特征
  • 抽象類實現的具體方法默認為虛的,但實現接口的類中的接口方法卻默認為非虛的,當然您也可以聲明為虛的
  • 如果抽象類實現接口,則可以把接口中方法映射到抽象類中作為抽象方法而不必實現,而在抽象類的子類中實現接口中方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM