C# 中 Overload(重载)与 Override(重写)的核心区别与实战解析

在 C# 面向对象编程(OOP)中,多态 是三大核心特性之一(封装、继承、多态)。

而在实际编码过程中,Overload(重载)Override(重写) 是最常见、也最容易被混淆的两种"多态体现方式"。

很多初学者会遇到以下困惑:

  • 方法名一样,为什么有时能共存,有时却编译报错?

  • 明明调用的是同一个方法名,运行结果却不一样?

  • virtualoverride 到底解决了什么问题?

本文将从 定义 → 特性 → 代码 → 底层逻辑 → 易错点 五个层次,彻底讲清楚 重载 vs 重写 的本质区别。


一、Overload(重载):同一类内的「静态多态」

1. 什么是方法重载?

方法重载(Overload) 指的是:

同一个类 中,定义多个方法名相同 ,但参数列表不同的方法。

参数列表不同可以体现在:

  • 参数个数不同

  • 参数类型不同

  • 参数顺序不同(不推荐,影响可读性)

⚠️ 注意

仅修改返回值类型,不能构成重载,否则会直接编译报错。


2. 重载的核心特性

重载的本质可以总结为三点:

  • 编译时多态(静态多态)

    在编译阶段,编译器就已经确定要调用哪个方法

  • 不依赖继承

  • 不需要任何关键字(virtual / override)

👉 核心目的

使用"同一个方法名",适配"不同参数场景",提升 API 的可读性与易用性。


3. 重载示例解析

cs 复制代码
class Shape
{
    // 无参数的 Draw
    public virtual void Draw()
    {
        Console.WriteLine("绘制一个形状");
    }

    // 带参数的 Draw ------ 重载
    public void Draw(int size)
    {
        Console.WriteLine($"绘制一个大小为 {size} 的形状");
    }
}

调用时:

cs 复制代码
Shape shape = new Shape();

shape.Draw();     // 匹配 Draw()
shape.Draw(10);   // 匹配 Draw(int)

📌 关键点

调用哪个方法,完全由参数列表决定,与对象运行时类型无关。


二、Override(重写):父子类间的「动态多态」

1. 什么是方法重写?

方法重写(Override) 指的是:

子类对基类中 virtual / abstract 修饰的方法 进行重新实现。

重写必须满足以下条件:

  • ✔️ 存在继承关系

  • ✔️ 基类方法使用 virtualabstract

  • ✔️ 子类方法使用 override

  • ✔️ 方法签名 完全一致(方法名 + 参数列表 + 返回值)


2. 重写的核心特性

  • 运行时多态(动态多态)

  • 行为取决于对象的实际类型

  • ✅ 是 OOP 中多态的核心机制

👉 核心目的

允许子类在不改变调用方式的前提下,定制或替换父类的行为。


3. 重写示例解析

cs 复制代码
class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("绘制一个圆形");
    }
}

关键调用代码:

cs 复制代码
Shape shape = new Circle();
shape.Draw();

📌 重点理解

  • 变量声明类型:Shape

  • 对象实际类型:Circle

  • 运行结果 :调用 Circle.Draw()

这正是动态多态的体现。


三、Overload 与 Override 的核心区别对比

对比维度 Overload(重载) Override(重写)
发生范围 同一个类内部 基类与子类之间
是否依赖继承 ❌ 不需要 ✅ 必须
方法名 相同 相同
参数列表 必须不同 必须完全一致
返回值 不能仅靠返回值区分 必须与基类一致
关键字 virtual / override
多态类型 编译时多态(静态) 运行时多态(动态)
决定时机 编译期 运行期
核心用途 适配不同参数 定制父类行为

四、完整示例:重载 + 重写的组合使用

1. 完整可运行代码

cs 复制代码
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. 程序运行结果

cs 复制代码
绘制一个形状
绘制一个大小为 10 的形状
绘制一个圆形

五、常见误区与踩坑总结

❌ 误区 1:仅修改返回值实现重载

cs 复制代码
int Foo();
string Foo(); // 编译错误

✔️ 原因:返回值不属于方法签名的一部分。


❌ 误区 2:基类没加 virtual,子类却 override

cs 复制代码
class A
{
    public void Test() {}
}

class B : A
{
    public override void Test() {} // 编译错误
}

❌ 误区 3:重写时修改参数列表

cs 复制代码
public override void Draw(int size) // ❌

❌ 误区 4:混淆声明类型与实际类型

cs 复制代码
Shape shape = new Circle();
shape.Draw();

👉 真正决定调用哪个方法的是:new Circle()


六、总结一句话记住区别

重载(Overload)

👉 同一个类中,方法名相同、参数不同编译期决定
重写(Override)

👉 父子类之间,方法签名一致、行为可替换运行期决定

相关推荐
饺子大魔王的男人1 小时前
Remote JVM Debug+cpolar 让 Java 远程调试超丝滑
java·开发语言·jvm
兩尛7 小时前
c++知识点2
开发语言·c++
fengfuyao9857 小时前
海浪PM谱及波形的Matlab仿真实现
开发语言·matlab
xiaoye-duck7 小时前
C++ string 底层原理深度解析 + 模拟实现(下)——面试 / 开发都适用
开发语言·c++·stl
Hx_Ma168 小时前
SpringMVC框架提供的转发和重定向
java·开发语言·servlet
期待のcode9 小时前
原子操作类LongAdder
java·开发语言
A_nanda10 小时前
c# MOdbus rto读写串口,如何不相互影响
算法·c#·多线程
lly20240610 小时前
C 语言中的结构体
开发语言
JAVA+C语言10 小时前
如何优化 Java 多主机通信的性能?
java·开发语言·php
青岑CTF11 小时前
攻防世界-Ics-05-胎教版wp
开发语言·安全·web安全·网络安全·php