1. 程式人生 > >面向對象3大特性之一:繼承

面向對象3大特性之一:繼承

prot 出現 初始化過程 子類 接口 我們 logs 類的構造函數 com

繼承

繼承表示一個類型(子類)派生自(繼承於)一個基類型(父類),該類型將擁有基類型的所有成員字段和函數(不包括構造函數和析構函數)。

註意:

  • 派生類繼承基類的所有成員,不管是public、private、protected還是其他的,不管是靜態的還是非靜態的;但是,雖然派生類繼承類基類所有的成員,基類卻只能訪問由public和protected修飾的成員(派生類繼承了基類所有的字段,但是只能訪問基類中public和protected修飾的成員)
 1     class Person
 2     {
 3         private string name = "張三";
 4         protected
int age = 20; 5 public bool gender = true; 6 7 public void ShowInfo_Person() 8 { 9 Console.WriteLine(this.name + ":" + this.age + ":" + this.gender); 10 } 11 } 12 13 class Chinese : Person 14 { 15 public void ShowInfo_Chinese() 16
{ 17 Chinese chinese = new Chinese(); 18 Console.WriteLine(chinese.age); 19 Console.WriteLine(chinese.gender); 20 //Console.WriteLine(chinese.name);//由於基類中name用private修飾,所以在派生類中無法訪問 21 } 22 } 23 24 class Program 25 { 26 static
void Main(string[] args) 27 { 28 Chinese chinese = new Chinese(); 29 chinese.ShowInfo_Person();//輸出結果:張三:20:True 此處通過派生類對象chinese可以調用基類中的ShowInfo_Person()方法,可以說明派生類也繼承了private修飾的name字段 30 Console.ReadKey(); 31 } 32 }
  • 派生類(子類)只能有一個直接基類(父類);但是繼承是可以傳遞的,例如ClassB派生自ClassA,同時ClassC派生自ClassB,那麽ClassC會繼承ClassB和ClassA中聲明的成員。
 1     class Animal
 2     {
 3         public void Method_Animal()
 4         {
 5             Console.WriteLine("Animal:---------------");
 6         }
 7     }
 8 
 9     class Dog : Animal
10     {
11         public void Method_Dog()
12         {
13             Console.WriteLine("Dog:***************");
14         }
15     }
16 
17     class ErHa : Dog
18     {
19         public void Method_ErHa()
20         {
21             Console.WriteLine("ErHa:...............");
22         }
23     }
24 
25     class Program
26     {
27         static void Main(string[] args)
28         {
29             ErHa eh = new ErHa();
30             eh.Method_Animal();
31             eh.Method_Dog();
32             eh.Method_ErHa();
33             Console.ReadKey();
34         }
35     }
  • C#不支持多重繼承,派生類只能有一個直接基類,但是可以實現多個接口,並通過實現多個接口達到多重繼承的目的
 1     interface IAnimal
 2     {
 3         void Method_Animal();
 4     }
 5 
 6     interface IDog
 7     {
 8         void Method_Dog();
 9     }
10     //實現多重繼承
11     class ErHa : IAnimal, IDog
12     {
13         public void Method_ErHa()
14         {
15             Console.WriteLine("ErHa:...............");
16         }
17 
18         public void Method_Animal()
19         {
20             Console.WriteLine("Animal:************");
21         }
22 
23         public void Method_Dog()
24         {
25             Console.WriteLine("Dog:---------------");
26         }
27     }
28 
29     class Program
30     {
31         static void Main(string[] args)
32         {
33             ErHa eh = new ErHa();
34             eh.Method_Animal();
35             eh.Method_Dog();
36             eh.Method_ErHa();
37             Console.ReadKey();
38         }
39     }
  • 結構不支持繼承
  • 派生類是對基類的擴展,派生類可以對基類進行成員的添加、重寫、覆蓋操作

構造函數

  • 派生類無法繼承基類的構造函數
  • 當調用派生類的構造函數時,默認先調用基類的無參構造函數,當基類沒有無參構造,需要派生類通過base關鍵字指定要調用的基類構造函數
 1     class Person
 2     {
 3         public Person()
4 { 5 Console.WriteLine("父類的無參構造函數被調用"); 6 } 7 } 8 9 class Student:Person
10 { 11 public Student() 12 { 13 Console.WriteLine("子類的無參構造函數被調用"); 14 } 15 } 16 17 class Program 18 { 19 static void Main(string[] args) 20 { 21 Student stu = new Student(); 22 Console.ReadKey(); 23 } 24 }

執行結果:

技術分享

當基類中不存在無參的構造函數時,需要通過base關鍵字派生類指定其要調用的基類的構造函數

 1     class Person
 2     {
 3         public Person(string name)
 4         {
 5             Console.WriteLine(name);
 6         }
 7     }
 8 
 9     class Student : Person
10     {
11         public Student()
12         {
13             Console.WriteLine();
14         }
15     }
16 
17     class Program
18     {
19         static void Main(string[] args)
20         {
21             Student stu = new Student();
22             Console.ReadKey();
23         }
24     }

以上代碼執行時會出現以下錯誤:

技術分享

如果我們想要使派生類調用基類的有參構造函數,而不是無參構造函數,就可以在派生類中通過base為其要調用的基類構造函數

 1     class Person
 2     {
 3         public Person(string name)
 4         {
 5             Console.WriteLine("姓名:"+name);
 6         }
 7     }
 8 
 9     class Student : Person
10     {
11         public Student(string name, string num)
12             : base(name)
13         {
14             Console.WriteLine("學號:"+num);
15         }
16     }
17 
18     class Program
19     {
20         static void Main(string[] args)
21         {
22             Student stu = new Student("張三", "0002");
23             Console.ReadKey();
24         }
25     }

技術分享

接下來我們通過以下代碼,了解一下子類對象的初始化過程

 1     class Person
 2     {
 3         public string name = "默認值:張三";
 4         public string gender = "默認值:男";
 5         public Person(string name, string gender)
 6         {
 7             this.name = name;
 8             this.gender = gender;
 9         }
10     }
11 
12     class Student : Person
13     {
14         public string num = "默認值:0002";
15         public Student(string name, string gender, string num)
16             : base(name, gender)
17         {
18             this.num = num;
19         }
20     }
21 
22     class Program
23     {
24         static void Main(string[] args)
25         {
26             Student stu = new Student("李四", "", "0004");
27             Console.WriteLine(stu.name);
28             Console.WriteLine(stu.gender);
29             Console.WriteLine(stu.num);
30             Console.ReadKey();
31         }
32     }

當在Main方法中實例化Student的對象時,首先在內存中分配了空間,內存中的初始狀態如下圖:

技術分享

調用派生類的構造函數,首先會調用基類的構造函數,由於我們在派生類Student中通過base關鍵字指定了派生類要調用的基類構造函數為public Person(string name,string gender),所以首先會用傳入的參數替換掉基類中成員的默認值,執行完成後,內存中的情況如下:

技術分享

執行完指定的基類構造函數後,執行派生類自身的構造函數,執行完成後,內存中的情況如下:

技術分享

至此,派生類對象實例化完成。

面向對象3大特性之一:繼承