继承

基本概念

  • 继承可以构建彼此关联且有共同行为的类
  • 被继承的叫做基类
  • 继承别人的叫做子类
  • 类图中,箭头由子类指向基类
  • 沿着类图上行,可以发现类的相同特征越少
  • 沿着类图下行,可以发现类的相同特征越多
  • 这就好像生物的分类——界门科目纲属种
  • 使用冒号可以继承一个基类
  • 一个类只允许继承一个类,这是一种保护

合并两个类

  1. 首先创建类图
  2. 找出两个类相同的字段与方法
  3. 把相同的放到一个基类中去
  4. 把不同的放在子类,要[[#覆盖]]的也需要写入
  5. 画上子类指向基类的箭头

覆盖

  • 在子类中,可以覆盖基类的方法
  • 举例,狗和猫都是动物,但是叫声不同,创建这样的类时,可以把Animal作为基类,Dog/Cat作为子类,在子类中覆盖Animal类的发出叫声的方法
  • 执行顺序:对于C#,执行方法时总是先从基类中寻找,如果在该子类中找不到,会沿着类图上行,一个个寻找,直到找到对应的方法 ^7e9264
  • 被覆盖的方法添加virtual关键字
  • 要覆盖别人的方法添加override关键字

隐藏的方法

  • 如果不添加这些关键字,则不会覆盖方法,而是隐藏了基类中的方法
  • 隐藏会导致产生两个同名的方法 ^b0994f
  • 在隐藏方法时,需要为子类中的方法添加new关键字
  • 如果隐藏了方法,调用时会根据引用来执行,也就是调用对应引用类型的方法
  • 如果调用了一个子类引用中该子类对应基类中的方法,且该方法中调用了另一个隐藏的方法(有两个同名方法),则会执行对应基类中的隐藏方法

继承的用法

  • 对于传递一个类的参数,如果该参数需要一个基类,则不仅可以传递该基类,还可以传递它的子类(任何一个都可以)
  • 传递后,只能使用对应传递的类中的内容
  • 比如传递一个基类,就不能使用它的子类的内容
  • 传递一个子类,也不能使用对应基类其他子类中的内容
  • 子类可以使用base关键字访问基类中的方法,即使它们被覆盖了

继承中的构造函数

  • 如果基类中有带参数的构造函数,则在子类中也必须调用其中一个
  • 但是,子类的构造函数与基类的构造函数可以有不同参数
  • 构造函数执行时,会从基类开始,沿着类图下行依次执行(这和覆盖的执行顺序正好相反)
  • 举例
1
2
3
4
5
6
7
8
9
10
11
12
13
class MyBase{
public MyBase(int number1)
{
Console.WriteLine(number1);
}
}

class MySub{
public MySub(int number1,int number2):base(number1){
Console.WriteLine(number2);
}
//output: number1 number2
}

知识拓展

  • 让类尽可能减少重叠,这是一个重要的设计原则,称作关注点分离
  • String.IsNullOrEmpty()可以检测一个字符串是否为空(即"")或null