首先看看菜鸟教程对于这个概念的解释:
C# 继承
继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时也有利于重用代码和节省开发时间。
当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个已有的类被称为的基类,这个新的类被称为派生类。
继承——面相对象的3大特性(封装、继承、多态)之一,其实直白来理解,就是为了更好的通过软件来描述这个世界的事务与关系,在程序开发领域引入的一个重要特性,它就像父亲继承祖父的遗传特性,然后儿子继承父亲的特征,同时子类的特征可以发生变异与新增。
当然,实际在程序开发中这种继承关系是很严格的,父类的所有内容,子类一个不拉的全部继承下来。
往往在项目中,有类的继承关系存在,就会伴随着 C# 重写(override)和覆盖(new),一般重写用的比较多。
下面一个简单的例子来温故C#类的继承:
先上类图:

看工程:

各个类的代码:
首先 “鸟类”:——祖先类
1 // 2 // 摘要: 3 // 支持 .NET Framework 类层次结构中的所有类,并为派生类提供低级别服务。 这是 .NET Framework 中所有类的最终基类;它是类型层次结构的根。 4 [ClassInterface(ClassInterfaceType.AutoDual)] 5 [ComVisible(true)] 6 public class Object 7 { 8 // 9 // 摘要: 10 // 初始化 System.Object 类的新实例。 11 [NonVersionableAttribute] 12 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 13 public Object(); 14 15 // 16 // 摘要: 17 // 在垃圾回收将某一对象回收前允许该对象尝试释放资源并执行其他清理操作。 18 [NonVersionableAttribute] 19 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 20 ~Object(); 21 22 // 23 // 摘要: 24 // 确定指定的对象实例是否被视为相等。 25 // 26 // 参数: 27 // objA: 28 // 要比较的第一个对象。 29 // 30 // objB: 31 // 要比较的第二个对象。 32 // 33 // 返回结果: 34 // 如果对象被视为相等,则为 true,否则为 false。 如果 objA 和 objB 均为 null,此方法返回 true。 35 public static bool Equals(Object objA, Object objB); 36 // 37 // 摘要: 38 // 确定指定的 System.Object 实例是否是相同的实例。 39 // 40 // 参数: 41 // objA: 42 // 要比较的第一个对象。 43 // 44 // objB: 45 // 要比较的第二个对象。 46 // 47 // 返回结果: 48 // 如果 objA 是与 objB 相同的实例,或两者均为 null,则为 true;否则为 false。 49 [NonVersionableAttribute] 50 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 51 public static bool ReferenceEquals(Object objA, Object objB); 52 // 53 // 摘要: 54 // 确定指定的对象是否等于当前对象。 55 // 56 // 参数: 57 // obj: 58 // 要与当前对象进行比较的对象。 59 // 60 // 返回结果: 61 // 如果指定的对象等于当前对象,则为 true,否则为 false。 62 public virtual bool Equals(Object obj); 63 // 64 // 摘要: 65 // 作为默认哈希函数。 66 // 67 // 返回结果: 68 // 当前对象的哈希代码。 69 public virtual int GetHashCode(); 70 // 71 // 摘要: 72 // 获取当前实例的 System.Type。 73 // 74 // 返回结果: 75 // 当前实例的准确运行时类型。 76 [SecuritySafeCritical] 77 public Type GetType(); 78 // 79 // 摘要: 80 // 返回表示当前对象的字符串。 81 // 82 // 返回结果: 83 // 表示当前对象的字符串。 84 public virtual string ToString(); 85 // 86 // 摘要: 87 // 创建当前 System.Object 的浅表副本。 88 // 89 // 返回结果: 90 // 当前 System.Object 的浅表副本。 91 [SecuritySafeCritical] 92 protected Object MemberwiseClone(); 93 }
实际上这个祖先类并非真正的祖先,它也是继承自C#的基类Object类
public class Bird { string message; double height; double weight; public int Height { get; set; } public int Weight { get; set; } public Bird() { } virtual public void fly(Bird name)//virtual 关键字是标记可被子类去重写的方法,换句话说只有virtual修饰的方法才能被子类重写;另外一个可以重写的修饰词是abstract { MessageBox.Show("I am a bird. I can fly!"); } virtual public void swim() { MessageBox.Show("I am a bird.I can't swim!"); } }
然后,分别有鸭子Duck类和鸡Chicken两个类来继承于Bird类;
1 class Duck : Bird 2 { 3 public override void fly(Bird name) 4 { 5 MessageBox.Show("I am a duck. I can't fly"); 6 } 7 public override void swim() 8 { 9 MessageBox.Show("I am a duck. I can swim"); 10 } 11 }
1 class Chicken : Bird 2 { 3 public override void fly(Bird name) 4 { 5 System.Windows.Forms.MessageBox.Show("I am chicken. I can't fly"); 6 } 7 8 public override void swim() 9 { 10 System.Windows.Forms.MessageBox.Show("I am chicken and I can't swim"); 11 } 12 }
接下来,烤鸭Roast_duck类继承于中间的鸭子Duck类;
1 class Roast_duck : Duck 2 { 3 public void eat() 4 { 5 MessageBox.Show("I am delicious. you can take me"); 6 } 7 public override void swim() 8 { 9 MessageBox.Show("I can not swim. I am a dish"); 10 } 11 }
现在,用一个简单的例子来演示和测试继承的效果;
在新建的窗体Form1的shown()事件下,编写如下代码:
1 private void Form1_Shown(object sender, EventArgs e) 2 { 3 Duck duck1 = new Duck(); 4 Bird bird1 = new Bird(); 5 Roast_duck roast_Duck1 = new Roast_duck(); 6 Chicken chicken1 = new Chicken(); 7 8 bird1.fly(duck1); 9 duck1.fly(bird1); 10 11 bird1.swim(); 12 duck1.swim(); 13 roast_Duck1.swim(); 14 roast_Duck1.eat(); 15 16 roast_Duck1.Weight = 3; 17 MessageBox.Show($"A roast duck1's weight is {roast_Duck1.Weight}Kg"); 18 }
F5运行结果:






