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)

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

相关推荐
落羽的落羽2 小时前
【C++】深入浅出“图”——图的基本概念与存储结构
服务器·开发语言·数据结构·c++·人工智能·机器学习·图搜索算法
巴塞罗那的风2 小时前
从蓝图到执行:智能体中的“战略家思维
开发语言·后端·ai·语言模型·golang
JAVA+C语言2 小时前
Python新手学习
开发语言·python·学习
六bring个六2 小时前
文件工具类(一)
开发语言·文件操作工具类
Matlab光学2 小时前
MATLAB仿真:离轴干涉法实现光学全息加密与解密
开发语言·matlab
小鸡吃米…2 小时前
Python - JSON
开发语言·python·json
JAVA+C语言2 小时前
C#——接口
开发语言·c#
黎雁·泠崖2 小时前
吃透指针通用用法:回调函数与 qsort 的使用和模拟
c语言·开发语言
whn19772 小时前
达梦数据库的整体负载变化查看
java·开发语言·数据库