一、多态
多态是从继承中引出来的概念,即不同的派生类对基类的相同方法表现出不同的行为。如下面例子中动物的游泳方法:
1 /// <summary> 2 /// 动物 3 /// </summary> 4 public class Animal 5 { 6 public string Swimming() 7 { 8 return "不会"; 9 } 10 } 11 /// <summary> 12 /// 鸡 13 /// </summary> 14 public class Chicken : Animal 15 { 16 17 } 18 /// <summary> 19 /// 狗 20 /// </summary> 21 public class Dog : Animal 22 { 23 } 24 /// <summary> 25 /// 蛙 26 /// </summary> 27 public class Frog : Animal 28 { 29 }
当用户使用派生类鸡的游泳方法时,由于基类的游泳方法满足鸡的需求,则直接调用基类的游泳方法返回不会;当用户使用派生类狗和蛙的游泳方法时,由于基类的游泳方法的实现不满足狗和蛙的需求,所以狗和蛙需要实现自己的逻辑。如何实现狗的狗刨和蛙的蛙泳?答案是重写(使用关键字virtual和override在派生类中重新实现基类的同名方法)。
1 public class Animal 2 { 3 //设计基类时对需要在派生类中重写的方法使用virtual修饰,使用virtual修饰的方法叫做虚方法 4 public virtual string Swimming() 5 { 6 return "不会"; 7 } 8 } 9 public class Dog : Animal 10 { 11 //派生类若要重写基类的方法,可使用override修饰与基类同名的方法,实现自己的行为,被override修饰的方法也可被重写 12 public override string Swimming() 13 { 14 return "狗刨"; 15 } 16 } 17 public class Frog : Animal 18 { 19 //派生类若要重写基类的方法,可使用override修饰与基类同名的方法,实现自己的行为,被override修饰的方法也可被重写 20 public override string Swimming() 21 { 22 return "蛙泳"; 23 } 24 }
上面的例子中,不同的派生类(鸡、狗、蛙)对基类(动物)的游泳方法表现出各自不同的结果,即类的多态特性。
也可以使用另一种方式遮挡来实现类的多态特性,即派生类使用new关键字来实现与基类同名方法的不同行为。
1 public class Animal 2 { 3 public string Swimming() 4 { 5 return "不会"; 6 } 7 } 8 public class Dog : Animal 9 { 10 //使用new关键字遮挡基类的同名方法,也可以使用到派生类的其他成员中 11 public new string Swimming() 12 { 13 return "狗刨"; 14 } 15 } 16 public class Frog : Animal 17 { 18 //使用new关键字遮挡基类的同名方法,也可以使用到派生类的其他成员中 19 public new string Swimming() 20 { 21 return "蛙泳"; 22 } 23 }
注:主要使用的情况是当我们没有修改基类的权限又希望实现派生类的多态特性时。
二、C#关键字:base
在派生类的方法中使用“base.基类方法名”可以复用基类的方法。
三、C#关键字:sealed
由于被override修饰的方法是隐式可重写的,所以当我们不希望被override修饰的方法被重写时,可以使用sealed关键字防止被重写。
1 public class Dog : Animal 2 { 3 //Dog类不希望自己的游泳方法被它的派生类重写 4 public sealed override string Swimming() 5 { 6 return "狗刨"; 7 } 8 }
注:在防止被重写中,sealed关键字必须与override关键字相同存在。
四、抽象类和抽象方法
当一个基类的作用只是为派生类提供公共成员,而无其他实际意义时,我们不希望用户通过new关键字创建这个基类,可将基类设计成抽象类,这样用户就不能用new关键字创建它。使用abstract关键字修饰类可使其变成抽象类。
当抽象类的某个方法在派生类中表现出多态性时,这个方法的实现对派生来说是无用的,我们希望所有派生类必须重写基类的这个方法,可将这个方法设计成抽象方法,这样抽象类的抽象方法不用提供默认实现并且派生类必须使用override重写此抽象方法。如果派生类不重写这个抽象方法自身也将成为一个抽象类。使用abstract关键字修饰方法可使其变成抽象方法。
1 /// <summary> 2 /// 可调度温度的电子设备 3 /// </summary> 4 public abstract class TemperatureElectric 5 { 6 protected int temperature; 7 8 public abstract int Up(); 9 10 public abstract int Down(); 11 } 12 /// <summary> 13 /// 空调 14 /// </summary> 15 public class AirConditioner : TemperatureElectric 16 { 17 public override int Up() 18 { 19 if (temperature < 30) 20 temperature += 1; 21 return temperature; 22 } 23 24 public override int Down() 25 { 26 if (temperature > 16) 27 temperature -= 1; 28 return temperature; 29 } 30 } 31 /// <summary> 32 /// 冰箱 33 /// </summary> 34 public class Refrigerator : TemperatureElectric 35 { 36 /// <summary> 37 /// 提升冷藏温度 38 /// </summary> 39 public override int Up() 40 { 41 if (temperature < 7) 42 temperature += 1;