C# 多态性
多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为”一个接口,多个功能”。 多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
一、静态多态性
在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:
1 2 3 |
• 函数重载 • 运算符重载 |
运算符重载将在下一章节讨论,接下来我们将讨论函数重载。
二、函数重载
您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。
下面的实例演示了几个相同的函数 print()
,用于打印不同的数据类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<span class="hljs-keyword">using</span> System; <span class="hljs-keyword">namespace</span> <span class="hljs-title">PolymorphismApplication</span> { <span class="hljs-keyword">class</span> <span class="hljs-title">Printdata</span> { <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> i</span>) </span>{ Console.WriteLine(<span class="hljs-string">"Printing int: {0}"</span>, i ); } <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span>(<span class="hljs-params"><span class="hljs-keyword">double</span> f</span>) </span>{ Console.WriteLine(<span class="hljs-string">"Printing float: {0}"</span> , f); } <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> s</span>) </span>{ Console.WriteLine(<span class="hljs-string">"Printing string: {0}"</span>, s); } <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>) </span>{ Printdata p = <span class="hljs-keyword">new</span> Printdata(); <span class="hljs-comment">// 调用 print 来打印整数</span> p.print(<span class="hljs-number">5</span>); <span class="hljs-comment">// 调用 print 来打印浮点数</span> p.print(<span class="hljs-number">500.263</span>); <span class="hljs-comment">// 调用 print 来打印字符串</span> p.print(<span class="hljs-string">"Hello C++"</span>); Console.ReadKey(); } } } |
当上面的代码被编译和执行时,它会产生下列结果:
1 2 3 4 |
Printing <span class="hljs-keyword">int</span>: <span class="hljs-number">5</span> Printing <span class="hljs-keyword">float</span>: <span class="hljs-number">500.263</span> Printing <span class="hljs-keyword">string</span>: Hello C++ |
三、动态多态性
C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。
请注意,下面是有关抽象类的一些规则:
- 您不能创建一个抽象类的实例。
- 您不能在一个抽象类外部声明一个抽象方法。
- 通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
下面的程序演示了一个抽象类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<span class="hljs-keyword">using</span> System; <span class="hljs-keyword">namespace</span> <span class="hljs-title">PolymorphismApplication</span> { <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> { <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">int</span> <span class="hljs-title">area</span>()</span>; } <span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span>: <span class="hljs-title">Shape</span> { <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> length; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> width; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span>(<span class="hljs-params"> <span class="hljs-keyword">int</span> a=<span class="hljs-number">0</span>, <span class="hljs-keyword">int</span> b=<span class="hljs-number">0</span></span>) </span>{ length = a; width = b; } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">int</span> <span class="hljs-title">area</span> () </span>{ Console.WriteLine(<span class="hljs-string">"Rectangle 类的面积:"</span>); <span class="hljs-keyword">return</span> (width * length); } } <span class="hljs-keyword">class</span> <span class="hljs-title">RectangleTester</span> { <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>) </span>{ Rectangle r = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">10</span>, <span class="hljs-number">7</span>); <span class="hljs-keyword">double</span> a = r.area(); Console.WriteLine(<span class="hljs-string">"面积: {0}"</span>,a); Console.ReadKey(); } } } |
当上面的代码被编译和执行时,它会产生下列结果:
1 2 3 |
Rectangle 类的面积: 面积: <span class="hljs-number">70</span> |
当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual 声明的。虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。
动态多态性是通过 抽象类 和 虚方法 实现的。
下面的程序演示了这点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
<span class="hljs-keyword">using</span> System; <span class="hljs-keyword">namespace</span> <span class="hljs-title">PolymorphismApplication</span> { <span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> { <span class="hljs-keyword">protected</span> <span class="hljs-keyword">int</span> width, height; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Shape</span>(<span class="hljs-params"> <span class="hljs-keyword">int</span> a=<span class="hljs-number">0</span>, <span class="hljs-keyword">int</span> b=<span class="hljs-number">0</span></span>) </span>{ width = a; height = b; } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">virtual</span> <span class="hljs-keyword">int</span> <span class="hljs-title">area</span>() </span>{ Console.WriteLine(<span class="hljs-string">"父类的面积:"</span>); <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; } } <span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span>: <span class="hljs-title">Shape</span> { <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span>(<span class="hljs-params"> <span class="hljs-keyword">int</span> a=<span class="hljs-number">0</span>, <span class="hljs-keyword">int</span> b=<span class="hljs-number">0</span></span>): <span class="hljs-title">base</span>(<span class="hljs-params">a, b</span>) </span>{ } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">int</span> <span class="hljs-title">area</span> () </span>{ Console.WriteLine(<span class="hljs-string">"Rectangle 类的面积:"</span>); <span class="hljs-keyword">return</span> (width * height); } } <span class="hljs-keyword">class</span> <span class="hljs-title">Triangle</span>: <span class="hljs-title">Shape</span> { <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Triangle</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> a = <span class="hljs-number">0</span>, <span class="hljs-keyword">int</span> b = <span class="hljs-number">0</span></span>): <span class="hljs-title">base</span>(<span class="hljs-params">a, b</span>) </span>{ } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">int</span> <span class="hljs-title">area</span>() </span>{ Console.WriteLine(<span class="hljs-string">"Triangle 类的面积:"</span>); <span class="hljs-keyword">return</span> (width * height / <span class="hljs-number">2</span>); } } <span class="hljs-keyword">class</span> <span class="hljs-title">Caller</span> { <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CallArea</span>(<span class="hljs-params">Shape sh</span>) </span>{ <span class="hljs-keyword">int</span> a; a = sh.area(); Console.WriteLine(<span class="hljs-string">"面积: {0}"</span>, a); } } <span class="hljs-keyword">class</span> <span class="hljs-title">Tester</span> { <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>) </span>{ Caller c = <span class="hljs-keyword">new</span> Caller(); Rectangle r = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">10</span>, <span class="hljs-number">7</span>); Triangle t = <span class="hljs-keyword">new</span> Triangle(<span class="hljs-number">10</span>, <span class="hljs-number">5</span>); c.CallArea(r); c.CallArea(t); Console.ReadKey(); } } } |
当上面的代码被编译和执行时,它会产生下列结果:
1 2 3 4 |
Rectangle 类的面积: 面积:<span class="hljs-number">70</span> Triangle 类的面积: 面积:<span class="hljs-number">25</span> |