封装、继承、多态,面向对象的三大特性,前两项理解相对容易,但要理解多态,特别是深入的了解,对于初学者而言可能就会有一定困难了。我一直认为学习OO 的最好方法就是结合实践,封装、继承在实际工作中的应用随处可见,但C# 多态呢?也许未必,可能不经意间用到也不会把它跟“ 多态” 这个词对应起来。在此抛砖引玉,大家讨论,个人能力有限,不足之处还请指正。
之前看到过类似的问题:如果面试时主考官要求你用一句话来描述多态,尽可能的精炼,你会怎么回答?当然答案有很多,每个人的理解和表达不尽相同,但我比较趋向这样描述:通过继承实现的不同对象调用相同的方法,表现出不同的行为,称之为多态。
1 、一个简单的C# 多态实现:
1. public class Animal
2. {
3. public virtual void Eat()
4. {
5. Console.WriteLine( "Animal Eat ..." );
6. }
7. }
8.
9. public class Cat : Animal
10. {
11. public override void Eat()
12. {
13. Console.WriteLine( "Cat Eat ..." );
14. }
15. }
16.
17. public class Dog : Animal
18. {
19. public override void Eat()
20. {
21. Console.WriteLine( "Dog Eat ..." );
22. }
23. }
24.
25. class Program
26. {
27. static void Main( string [] args)
28. {
29. Animal[] animals = new Animal[3];
30.
31. animals[0] = new Animal();
32. animals[1] = new Cat();
33. animals[2] = new Dog();
34.
35. for ( int i = 0; i < 3; i++)
36. {
37. animals[i].Eat();
38. }
39. }
40. }
输出结果:
Animal Eat ...
Cat Eat ...
Dog Eat ...
OK ,从上面的例子可以看出,通过继承,使得Animal 对象数组中的不同的对象,在调用Eat() 方法时,表现出了不同的行为,这就是一个最简单的多态示例。
2 、如果继承中使用new 而不是override 关键字
41. public class Animal
42. {
43. public virtual void Eat()
44. {
45. Console.WriteLine( "Animal Eat ..." );
46. }
47. }
48.
49. public class Cat : Animal
50. {
51. public override void Eat()
52. {
53. Console.WriteLine( "Cat Eat ..." );
54. }
55. }
56.
57. public class Dog : Animal
58. {
59. // 注意此处用了 new 而不再是 override 关键字
60. public new void Eat()
61. {
62. Console.WriteLine( "Dog Eat ..." );
63. }
64. }
65.
66. class Program
67. {
68. static void Main( string [] args)
69. {
70. Animal animal = new Animal();
71. animal.Eat();
72.
73. Animal cat = new Cat();
74. cat.Eat();
75.
76. Animal dog = new Dog();
77. dog.Eat();
78. }
79. }
输出结果:
Animal Eat ...
Cat Eat ...
Animal Eat ...
从结果中可以看出,当派生类Dog 的Eat() 方法使用new 修饰时,Dog 的对象转换为Animal 对象后,调用的是Animal 类中的Eat() 方法。其实可以理解为,使用new 关键字后,使得Dog 中的Eat() 方法和Animal 中的Eat() 方法成为毫不相关的两个方法,只是它们的名字碰巧相同而已。也由此可以看出:多态,依赖override 实现。
3 、多重继承
如果class A 有一个virtual method() ,class B 继承于class A ,并override method() ,class C 又继承于class B ,那么class C 是否可以继续override method() 并实现多态呢?看下面的例子:
80. public class Animal
81. {
82. public virtual void Eat()
83. {
84. Console.WriteLine( "Animal Eat " );
85. }
86. }
87.
88. public class Dog : Animal
89. {
90. public override void Eat()
91. {
92. Console.WriteLine( "Dog Eat " );
93. }
94. }
95.
96. public class WolfDog : Dog
97. {
98. public override void Eat()
99. {
100. Console.WriteLine( "WolfDog Eat " );
101. }
102. }
103.
104. class Program
105. {
106. static void Main( string [] args)
107. {
108. Animal animal = new Animal();
109. animal.Eat();
110.
111. Animal dog = new Dog();
112. dog.Eat();
113.
114. Animal wolfdog = new WolfDog();
115. wolfdog.Eat();
116.
117. }
118. }
输出结果:
Animal Eat ...
Dog Eat ...
WolfDog Eat ...
OK ,现在得到了肯定的答案,不管继承关系包含了多少层,都可以在子类中对父类中已经重写的方法继续进行重写。即如果父类方法用override 修饰,子类继承了该方法,同时也可以用override 修饰,多重继承中的C# 多态就是如此实现。要想终止这种重写,只需重写方法时使用sealed 关键字。