在 C# 面向对象编程(OOP)中,多态是三大核心特性之一(封装、继承、多态)。
而在实际编码过程中,Overload(重载) 与 Override(重写) 是最常见、也最容易被混淆的两种“多态体现方式”。
很多初学者会遇到以下困惑:
-
方法名一样,为什么有时能共存,有时却编译报错?
-
明明调用的是同一个方法名,运行结果却不一样?
-
virtual、override到底解决了什么问题?
本文将从 定义 → 特性 → 代码 → 底层逻辑 → 易错点 五个层次,彻底讲清楚 重载 vs 重写 的本质区别。
一、Overload(重载):同一类内的「静态多态」
1. 什么是方法重载?
方法重载(Overload) 指的是:
在同一个类中,定义多个方法名相同,但参数列表不同的方法。
参数列表不同可以体现在:
-
参数个数不同
-
参数类型不同
-
参数顺序不同(不推荐,影响可读性)
⚠️ 注意
仅修改返回值类型,不能构成重载,否则会直接编译报错。
2. 重载的核心特性
重载的本质可以总结为三点:
-
✅ 编译时多态(静态多态)
在编译阶段,编译器就已经确定要调用哪个方法 -
✅ 不依赖继承
-
✅ 不需要任何关键字(virtual / override)
👉 核心目的:
使用“同一个方法名”,适配“不同参数场景”,提升 API 的可读性与易用性。
3. 重载示例解析
class Shape
{
// 无参数的 Draw
public virtual void Draw()
{
Console.WriteLine("绘制一个形状");
}
// 带参数的 Draw —— 重载
public void Draw(int size)
{
Console.WriteLine($"绘制一个大小为 {size} 的形状");
}
}
调用时:
Shape shape = new Shape();
shape.Draw(); // 匹配 Draw()
shape.Draw(10); // 匹配 Draw(int)
📌 关键点
调用哪个方法,完全由参数列表决定,与对象运行时类型无关。
二、Override(重写):父子类间的「动态多态」
1. 什么是方法重写?
方法重写(Override) 指的是:
子类对基类中 virtual / abstract 修饰的方法 进行重新实现。
重写必须满足以下条件:
-
✔️ 存在继承关系
-
✔️ 基类方法使用
virtual或abstract -
✔️ 子类方法使用
override -
✔️ 方法签名 完全一致(方法名 + 参数列表 + 返回值)
2. 重写的核心特性
-
✅ 运行时多态(动态多态)
-
✅ 行为取决于对象的实际类型
-
✅ 是 OOP 中多态的核心机制
👉 核心目的:
允许子类在不改变调用方式的前提下,定制或替换父类的行为。
3. 重写示例解析
class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("绘制一个圆形");
}
}
关键调用代码:
Shape shape = new Circle();
shape.Draw();
📌 重点理解
-
变量声明类型:
Shape -
对象实际类型:
Circle -
运行结果:调用
Circle.Draw()
这正是动态多态的体现。
三、Overload 与 Override 的核心区别对比
| 对比维度 | Overload(重载) | Override(重写) |
|---|---|---|
| 发生范围 | 同一个类内部 | 基类与子类之间 |
| 是否依赖继承 | ❌ 不需要 | ✅ 必须 |
| 方法名 | 相同 | 相同 |
| 参数列表 | 必须不同 | 必须完全一致 |
| 返回值 | 不能仅靠返回值区分 | 必须与基类一致 |
| 关键字 | 无 | virtual / override |
| 多态类型 | 编译时多态(静态) | 运行时多态(动态) |
| 决定时机 | 编译期 | 运行期 |
| 核心用途 | 适配不同参数 | 定制父类行为 |
四、完整示例:重载 + 重写的组合使用
1. 完整可运行代码
using System;
class Shape
{
// 可被重写的虚方法
public virtual void Draw()
{
Console.WriteLine("绘制一个形状");
}
// 重载方法
public void Draw(int size)
{
Console.WriteLine($"绘制一个大小为 {size} 的形状");
}
}
class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("绘制一个圆形");
}
}
class Program
{
static void Main()
{
Shape shape = new Shape();
Circle circle = new Circle();
shape.Draw(); // Shape.Draw()
shape.Draw(10); // Shape.Draw(int)
shape = circle;
shape.Draw(); // Circle.Draw()
}
}
2. 程序运行结果
绘制一个形状
绘制一个大小为 10 的形状
绘制一个圆形
五、常见误区与踩坑总结
❌ 误区 1:仅修改返回值实现重载
int Foo();
string Foo(); // 编译错误
✔️ 原因:返回值不属于方法签名的一部分。
❌ 误区 2:基类没加 virtual,子类却 override
class A
{
public void Test() {}
}
class B : A
{
public override void Test() {} // 编译错误
}
❌ 误区 3:重写时修改参数列表
public override void Draw(int size) // ❌
❌ 误区 4:混淆声明类型与实际类型
Shape shape = new Circle();
shape.Draw();
👉 真正决定调用哪个方法的是:new Circle()
六、总结一句话记住区别
重载(Overload)
👉 同一个类中,方法名相同、参数不同,编译期决定
重写(Override)
👉 父子类之间,方法签名一致、行为可替换,运行期决定

被折叠的 条评论
为什么被折叠?



