面向對象3大特性之一:繼承
阿新 • • 發佈:2017-07-22
prot 出現 初始化過程 子類 接口 我們 logs 類的構造函數 com
繼承
繼承表示一個類型(子類)派生自(繼承於)一個基類型(父類),該類型將擁有基類型的所有成員字段和函數(不包括構造函數和析構函數)。
註意:
- 派生類繼承基類的所有成員,不管是public、private、protected還是其他的,不管是靜態的還是非靜態的;但是,雖然派生類繼承類基類所有的成員,基類卻只能訪問由public和protected修飾的成員(派生類繼承了基類所有的字段,但是只能訪問基類中public和protected修飾的成員)
1 class Person 2 { 3 private string name = "張三"; 4 protectedint 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 staticvoid 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大特性之一:繼承