C#继承用法详解(附带实例)
在 C# 面向对象的程序设计中,类是可以继承(inheritance)的,其中被继承的类称为父类(parent class)、超类(superclass)或基类(base class),继承的类称为子类(child class或subclass)或衍生类(derived class)。
类继承的最大优点是许多父类的字段、属性与方法,在子类中不用重新设计,可以直接引用,另外子类也可以有自己的字段、属性与方法。
【实例 2】这是一个 Dog 类,这个类的字段是 name,代表动物的名字。然后有 3 个方法,分别是 Eat()、Sleep() 和 Barking(),这 3 个方法会分别列出“name正在吃食物”、“name正在睡觉”和“name正在叫”。
【实例 3】这是一个 Bird(鸟)类,这个类的字段是 name,代表动物的名字。然后有 3 个方法,分别是 Eat()、Sleep() 和 Flying(),这 3 个方法会分别列出“name正在吃食物”、“name正在睡觉”和“name正在飞”。
其实狗和鸟都是动物,由上图关系可以看出 Dog 类、Bird 类与 Animal 类都有相同的字段 name,同时有相同的方法 Eat() 和 Sleep(),然后 Dog 类有属于自己的方法 Barking(),Bird 类有属于自己的方法 Flying()。
如果我们将上述 3 个程序写成一个程序,则将创造一个冗长的程序代码,可是如果我们利用 C# 面向对象的继承(inheritance)概念,整个程序将简化许多。
若是从 Animal 类和 Dog 类的关系看,Animal 类是 Dog 类的父类,或者 Dog 类是 Animal 类的子类,Dog 类可以继承 Animal 类,可以用下列方式设计 Dog 类。
【实例 4】将实例 1 和实例 2 做简化省略属性,组成一个程序,以体会子类 Dog 继承父类 Animal 的方法。
上述实例中,Dog 类继承了 Animal 类,我们可以称为单一继承。
其实我们创建一个子类的对象时,C# 在调用子类的构造方法前会先调用父类的构造方法。其实这个概念很简单,子类继承了父类的内容,所以子类在创建本身的对象前,一定要先初始化所继承的父类的内容,下列程序实例将验证这个概念。
【实例 5】创建一个 Dog 类的对象,观察在调用其本身的构造方法前,父类 Animal 的构造方法会先被调用。
【实例 6】这个程序基本上是组合了实例 1 和实例 2,但是将父类 Animal 的属性 name 声明为 public。
类继承的最大优点是许多父类的字段、属性与方法,在子类中不用重新设计,可以直接引用,另外子类也可以有自己的字段、属性与方法。

从3个简单的C#程序谈起
【实例 1】这是一个 Animal 动物类,这个类的字段是 name,代表动物的名字。然后有两个方法,分别是 Eat() 和 Sleep(),这两个方法会分别列出“name正在吃食物”和“name正在睡觉”。Animal animal = new Animal("Lily"); animal.Eat(); animal.Sleep(); public class Animal { string name; public Animal (string name) => this.name = name; public void Eat() { Console.WriteLine($"{name} 正在吃食物"); } public void Sleep() { Console.WriteLine($"{name} 正在睡觉"); } }执行结果为:
Lily 正在吃食物
Lily 正在睡觉
【实例 2】这是一个 Dog 类,这个类的字段是 name,代表动物的名字。然后有 3 个方法,分别是 Eat()、Sleep() 和 Barking(),这 3 个方法会分别列出“name正在吃食物”、“name正在睡觉”和“name正在叫”。
Dog dog = new Dog("Haly"); dog.Eat(); dog.Sleep(); dog.Barking(); public class Dog { string name; public Dog(string name) => this.name = name; public void Eat() { Console.WriteLine($"{name} 正在吃食物"); } public void Sleep() { Console.WriteLine($"{name} 正在睡觉"); } public void Barking() { Console.WriteLine($"{name} 正在叫"); } }执行结果为:
Haly 正在吃食物
Haly 正在睡觉
Haly 正在叫
【实例 3】这是一个 Bird(鸟)类,这个类的字段是 name,代表动物的名字。然后有 3 个方法,分别是 Eat()、Sleep() 和 Flying(),这 3 个方法会分别列出“name正在吃食物”、“name正在睡觉”和“name正在飞”。
Bird bird = new Bird("CiCi"); bird.Eat(); bird.Sleep(); bird.Flying(); public class Bird { string name; public Bird(string name) => this.name = name; public void Eat() { Console.WriteLine($"{name} 正在吃食物"); } public void Sleep() { Console.WriteLine($"{name} 正在睡觉"); } public void Flying() { Console.WriteLine($"{name} 正在飞"); } }执行结果为:
CiCi 正在吃食物
CiCi 正在睡觉
CiCi 正在飞

其实狗和鸟都是动物,由上图关系可以看出 Dog 类、Bird 类与 Animal 类都有相同的字段 name,同时有相同的方法 Eat() 和 Sleep(),然后 Dog 类有属于自己的方法 Barking(),Bird 类有属于自己的方法 Flying()。
如果我们将上述 3 个程序写成一个程序,则将创造一个冗长的程序代码,可是如果我们利用 C# 面向对象的继承(inheritance)概念,整个程序将简化许多。
C#继承的语法
C# 的继承需使用关键词符号“:”,语法如下:存取修饰词 class 子类名称 : 父类名称 { // 子类字段、属性与方法 }
若是从 Animal 类和 Dog 类的关系看,Animal 类是 Dog 类的父类,或者 Dog 类是 Animal 类的子类,Dog 类可以继承 Animal 类,可以用下列方式设计 Dog 类。
public class Dog : Animal { // Dog类字段、属性与方法 }
【实例 4】将实例 1 和实例 2 做简化省略属性,组成一个程序,以体会子类 Dog 继承父类 Animal 的方法。
Dog dog = new Dog(); dog.Eat(); dog.Sleep(); dog.Barking(); public class Animal { public void Eat() { Console.WriteLine("正在吃食物"); } public void Sleep() { Console.WriteLine("正在睡觉"); } } public class Dog : Animal { public void Barking() { Console.WriteLine("正在叫"); } }执行结果为:
正在吃食物
正在睡觉
正在叫

上述实例中,Dog 类继承了 Animal 类,我们可以称为单一继承。
C#构造方法的调用
正常的类一定有字段,当我们声明创建子类对象时,可以利用子类本身的构造方法初始化自己的字段。至于子类所继承的父类字段,则由父类自身的构造方法初始化其本身的字段。其实我们创建一个子类的对象时,C# 在调用子类的构造方法前会先调用父类的构造方法。其实这个概念很简单,子类继承了父类的内容,所以子类在创建本身的对象前,一定要先初始化所继承的父类的内容,下列程序实例将验证这个概念。
【实例 5】创建一个 Dog 类的对象,观察在调用其本身的构造方法前,父类 Animal 的构造方法会先被调用。
Dog dog = new Dog(); dog.Eat(); dog.Sleep(); dog.Barking(); public class Animal { public Animal() => Console.WriteLine("执行Animal构造方法 ..."); public void Eat() { Console.WriteLine("正在吃食物"); } public void Sleep() { Console.WriteLine("正在睡觉"); } } public class Dog : Animal { public Dog() => Console.WriteLine("执行Dog构造方法 ..."); public void Barking() { Console.WriteLine("正在叫"); } }执行结果为:
执行Animal构造方法 ...
执行Dog构造方法 ...
正在吃食物
正在睡觉
正在叫
C#父类属性为public时子类初始化父类属性
现在我们扩充方案实例 5,扩充父类的属性 name,同时将 name 声明为 public,由于子类可以继承父类的所有 public 属性,所以这时可以由子类的构造方法初始化父类的属性 name。【实例 6】这个程序基本上是组合了实例 1 和实例 2,但是将父类 Animal 的属性 name 声明为 public。
Dog dog = new Dog("Haly"); dog.Eat(); dog.Sleep(); dog.Barking(); public class Animal { public string name; public void Eat() { Console.WriteLine($"{name} 正在吃食物"); } public void Sleep() { Console.WriteLine($"{name} 正在睡觉"); } } public class Dog : Animal { public Dog(string name) { this.name = name; // 构造方法使用父类的name属性 } public void Barking() { Console.WriteLine($"{name} 正在叫"); } }执行结果为:
Haly 正在吃食物
Haly 正在睡觉
Haly 正在叫