C# 多态完全指南:静态多态与动态多态(重载、重写、虚方法)
多态意为"多种形态"。面向对象编程中常表达为"一个接口,多种功能"。多态分为静态和动态:
- 静态多态:编译时确定函数响应(早绑定)
- 动态多态:运行时决定函数响应(晚绑定)
静态多态
C# 通过两种技术实现静态多态:
- 函数重载
- 运算符重载(下章详解)
函数重载
同一作用域内可有多个同名函数定义,参数类型/数量不同即可。仅返回类型不同不能重载。
示例
using System;
namespace PolymorphismApplication {
class Printdata {
void print(int i) { Console.WriteLine("Printing int: {0}", i); }
void print(double f) { Console.WriteLine("Printing float: {0}", f); }
void print(string s) { Console.WriteLine("Printing string: {0}", s); }
static void Main(string[] args) {
Printdata p = new Printdata();
p.print(5); // Printing int: 5
p.print(500.263); // Printing float: 500.263
p.print("Hello C#"); // Printing string: Hello C#
Console.ReadKey();
}
}
}
动态多态
C# 允许创建抽象类提供接口的部分实现,派生类完成实现。抽象类包含抽象方法(无实现),由派生类实现。
抽象类规则
- 不能创建抽象类实例
- 抽象方法只能声明在抽象类中
sealed类不能继承,抽象类不能声明为sealed
抽象类示例
using System;
namespace PolymorphismApplication {
abstract class Shape {
public abstract int area();
}
class Rectangle : Shape {
private int length, width;
public Rectangle(int a = 0, int b = 0) { length = a; width = b; }
public override int area() {
Console.WriteLine("Rectangle class area :");
return width * length;
}
}
class RectangleTester {
static void Main(string[] args) {
Rectangle r = new Rectangle(10, 7);
double a = r.area();
Console.WriteLine("Area: {0}", a); // 70
Console.ReadKey();
}
}
}
虚方法与动态分派
当基类方法需由派生类不同实现时,使用 virtual 关键字。调用在运行时根据实际对象类型决定。
虚方法示例
using System;
namespace PolymorphismApplication {
class Shape {
protected int width, height;
public Shape(int a = 0, int b = 0) { width = a; height = b; }
public virtual int area() {
Console.WriteLine("Parent class area :");
return 0;
}
}
class Rectangle : Shape {
public Rectangle(int a = 0, int b = 0) : base(a, b) { }
public override int area() {
Console.WriteLine("Rectangle class area :");
return width * height;
}
}
class Triangle : Shape {
public Triangle(int a = 0, int b = 0) : base(a, b) { }
public override int area() {
Console.WriteLine("Triangle class area :");
return width * height / 2;
}
}
class Caller {
public void CallArea(Shape sh) {
int a = sh.area();
Console.WriteLine("Area: {0}", a);
}
}
class Tester {
static void Main(string[] args) {
Caller c = new Caller();
Rectangle r = new Rectangle(10, 7);
Triangle t = new Triangle(10, 5);
c.CallArea(r); // Rectangle class area: 70
c.CallArea(t); // Triangle class area: 25
Console.ReadKey();
}
}
}
静态 vs 动态多态对比
| 特性 | 静态多态(重载) | 动态多态(重写) |
|---|---|---|
| 绑定时间 | 编译时 | 运行时 |
| 实现方式 | 同名不同参数 | virtual/override |
| 性能 | 略高(无虚表查找) | 虚表查找开销 |
| 灵活性 | 编译期固定 | 运行期可扩展 |
| 典型场景 | 工具方法、数学运算 | 框架扩展、插件架构 |
核心原则:优先使用重载解决同一语义不同参数场景;需要运行时行为差异时使用虚方法/抽象方法。
C语言
- C# 类与对象:面向对象编程的基石
- 理解 C# 访问修饰符:public、private、protected、internal 等完全指南
- C# static 关键字:静态变量、方法与类完全掌握
- 掌握 C# 抽象类与抽象方法:实战指南
- 理解 C# 嵌套类:定义、访问与继承实战
- 理解 C# 分部类与分部方法
- C++ 类模板实战指南:编写灵活的类型无关代码
- C++多态实战指南:虚函数、动态绑定与纯虚函数
- 精通 Java 匿名内部类:定义、语法与实战示例
- 掌握 Java ObjectOutputStream:序列化、核心方法与实战示例
- 掌握 Java 泛型:构建可复用、类型安全的代码
- 掌握 Java 文件操作:java.io 包下的创建、读取、写入与删除