ibcadmin 发表于 2019-9-26 09:15:35

C#面向对象之多态

<h1>一、多态</h1>
<p>  多态是从继续中引出来的概念,即差别的派生类对基类的类似方法表现出差别的举动。如下面例子中动物的游泳方法:</p>

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 }

<p>当用户利用派生类鸡的游泳方法时,由于基类的游泳方法满足鸡的需求,则直接调用基类的游泳方法返回不会;当用户利用派生类狗和蛙的游泳方法时,由于基类的游泳方法的实现不满足狗和蛙的需求,以是狗和蛙必要实现自己的逻辑。怎样实现狗的狗刨和蛙的蛙泳?答案是重写(利用关键字virtual和override在派生类中重新实现基类的同名方法)。</p>

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 }

<p>上面的例子中,差别的派生类(鸡、狗、蛙)对基类(动物)的游泳方法表现出各自差别的结果,即类的多态特性。</p>
<p> </p>
<p>  也可以利用另一种方式遮挡来实现类的多态特性,即派生类利用new关键字来实现与基类同名方法的差别举动。</p>

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 }

<p>注:重要利用的情况是当我们没有修改基类的权限又希望实现派生类的多态特性时。</p>
<p> </p>
<h1>二、C#关键字:base</h1>
<p>  在派生类的方法中利用“base.基类方法名”可以复用基类的方法。</p>
<p> </p>
<h1>三、C#关键字:sealed</h1>
<p>  由于被override修饰的方法是隐式可重写的,以是当我们不希望被override修饰的方法被重写时,可以利用sealed关键字防止被重写。</p>

1 public class Dog : Animal
2 {
3   //Dog类不希望自己的游泳方法被它的派生类重写
4   public sealed override string Swimming()
5   {
6         return "狗刨";
7   }
8 }

<p>注:在防止被重写中,sealed关键字必须与override关键字类似存在。</p>
<p> </p>
<h1>四、抽象类和抽象方法</h1>
<p>  当一个基类的作用只是为派生类提供公共成员,而无其他实际意义时,我们不希望用户通过new关键字创建这个基类,可将基类设计成抽象类,这样用户就不能用new关键字创建它。利用abstract关键字修饰类可使其变成抽象类。</p>
<p>  当抽象类的某个方法在派生类中表现出多态性时,这个方法的实现对派生来说是无用的,我们希望全部派生类必须重写基类的这个方法,可将这个方法设计成抽象方法,这样抽象类的抽象方法不消提供默认实现而且派生类必须利用override重写此抽象方法。如果派生类不重写这个抽象方法自身也将成为一个抽象类。利用abstract关键字修饰方法可使其变成抽象方法。</p>

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;
43         return temperature;
44   }
45
46   /// <summary>
47   /// 低沉冷藏温度
48   /// </summary>
49   public override int Down()
50   {
51         if (temperature > 3)
52             temperature -= 1;
53         return temperature;
54   }
55 }

<p> </p>
<h1>五、几种概念的对比</h1>
<p>1、重载与重写</p>
<p>重载和重写的类似点在于他们都是对同名的方法利用。</p>
<p>重载和重写的差别点:在利用范围上,前者利用在单个类中,后者利用在两个或多个有继续关系的类中;在利用意图上,前者是写法上的简化,后者是功能上的扩展。</p>
<p>2、重写与遮挡</p>
<p>重写与遮挡的类似点在于他们都是对基类同名方法的扩展。</p>
<p>重写与遮挡的差别点在于,通过A a = new B();B继续于A,前者调用B的同名方法,而后者调用的是A的同名方法;前者用于自动设计,后者用于被动修改。</p>

1 public class RealizeObject
2 {
3   public void Realize()
4   {
5         //Dog是通过virtual重写的Animal
6         Animal animal = new Dog();
7         animal.Swimming();//输出的狗刨
8
9         //Dog是通过new遮挡的Animal
10         Animal animal = new Dog();
11         animal.Swimming();//输出的不会
12   }
13 }

<p>3、虚方法和抽象方法</p>
<p>虚方法与抽象方法的类似点在于他们都可以被重写。</p>
<p>虚方法与抽象方法的差别点:在利用范围上前者大于后者,前者利用在非密封类中,后者只能利用在抽象类中;在利用方式上,前者必须有实现部分,后者不能有实现部分;在派生类中,前者可重写可不重写,后者必须重写。</p>
<p>4、抽象类与接口范例的区别(见C#接口范例)</p>
<p> </p><br><br/><br/><br/><br/><br/>来源:<a href="https://www.cnblogs.com/yaojieyuan/archive/2019/09/25/11587026.html" target="_blank">https://www.cnblogs.com/yaojieyuan/archive/2019/09/25/11587026.html</a>
页: [1]
查看完整版本: C#面向对象之多态