编辑
2025-09-22
C#
00

目录

方法重写的特性
多态性
灵活性
可维护性
方法重写的应用场景
定制化行为
扩展基类功能
实现设计模式
方法重写的语法与规则
实例解析
示例 1:动物叫声
示例 2:车辆启动
示例 3:图形绘制
示例 4:员工薪资计算
示例 5:模板方法模式
注意事项
总结

方法重写(Method Overriding)是 C# 面向对象编程中的一个核心概念,它允许派生类根据需要改变继承自基类的方法实现。通过方法重写,可以实现多态性,使程序更加灵活、易于扩展和维护。本文将详细介绍方法重写的特性和应用场景,并通过多个实例加深对这一概念的理解。

实现项目中方法重写比较常用。

方法重写的特性

多态性

  • 定义:多态性允许相同的接口调用,根据对象的实际类型执行不同的操作。
  • 实现:通过在基类中定义虚方法(virtual),在派生类中重写(override)这些方法来实现多态。

灵活性

  • 重写基类的方法,派生类可以根据自身需求修改或扩展方法的实现,而无需修改基类的代码。

可维护性

  • 通过方法重写,可以在不改变基类代码的情况下,对其行为进行修改或扩展,增强了代码的可维护性和可扩展性。

方法重写的应用场景

定制化行为

当派生类需要提供与基类不同的具体实现时,可通过重写基类的方法来实现定制化行为。

扩展基类功能

在不改变基类的情况下,派生类可以通过调用基类方法并添加新的功能来扩展基类的行为。

实现设计模式

某些设计模式(如模板方法模式)需要通过在派生类中重写基类方法来实现特定的业务逻辑。

方法重写的语法与规则

  • 基类方法:使用 virtual 关键字标识可被重写的方法。
C#
public virtual void MethodName() { // 基类方法实现 }
  • 派生类方法:使用 override 关键字重写基类的方法。
C#
public override void MethodName() { // 派生类方法实现 }
  • 调用基类方法:在重写的方法中,可以使用 base.MethodName() 调用基类的方法实现。

实例解析

示例 1:动物叫声

目标:演示如何通过方法重写实现多态性。

C#
namespace App06 { public class Animal { public virtual void Speak() { Console.WriteLine("动物发出声音。"); } } public class Dog : Animal { public override void Speak() { Console.WriteLine("狗叫:汪汪!"); } } public class Cat : Animal { public override void Speak() { Console.WriteLine("猫叫:喵喵!"); } } internal class Program { static void Main(string[] args) { // 使用示例 Animal[] animals = { new Dog(), new Cat(), new Animal() }; foreach (var animal in animals) { animal.Speak(); } } } }

image.png

说明

  • 基类 Animal 定义了虚方法 Speak()
  • DogCat 类重写了 Speak() 方法,实现各自的叫声。
  • 通过基类引用调用 Speak() 方法,根据实际对象类型执行不同的实现。

示例 2:车辆启动

目标:展示如何在重写的方法中调用基类的方法。

C#
namespace App06 { public class Vehicle { public virtual void Start() { Console.WriteLine("车辆启动。"); } } public class Car : Vehicle { public override void Start() { base.Start(); // 调用基类的 Start 方法 Console.WriteLine("汽车发动引擎。"); } } internal class Program { static void Main(string[] args) { // 使用示例 Vehicle myCar = new Car(); myCar.Start(); } } }

image.png

说明

  • Car 类重写了 Start() 方法,并使用 base.Start() 调用了基类的方法,实现了功能的扩展。

示例 3:图形绘制

目标:演示抽象类和方法重写的结合使用。

C#
namespace App06 { public abstract class Shape { public abstract void Draw(); } public class Circle : Shape { public override void Draw() { Console.WriteLine("绘制一个圆形。"); } } public class Rectangle : Shape { public override void Draw() { Console.WriteLine("绘制一个矩形。"); } } internal class Program { static void Main(string[] args) { // 使用示例 List<Shape> shapes = new List<Shape> { new Circle(), new Rectangle() }; foreach (var shape in shapes) { shape.Draw(); } } } }

image.png

说明

  • 抽象类 Shape 定义了抽象方法 Draw(),强制派生类必须实现该方法。
  • 派生类 CircleRectangle 实现了各自的 Draw() 方法。

示例 4:员工薪资计算

目标:通过方法重写计算不同类型员工的薪资。

C#
namespace App06 { public class Employee { public virtual double CalculateSalary() { return 3000.0; // 基本工资 } } public class Manager : Employee { public override double CalculateSalary() { return base.CalculateSalary() + 2000.0; // 基本工资 + 管理奖金 } } public class Salesperson : Employee { public double SalesAmount { get; set; } public override double CalculateSalary() { return base.CalculateSalary() + SalesAmount * 0.05; // 基本工资 + 销售提成 } } internal class Program { static void Main(string[] args) { // 使用示例 Employee emp1 = new Manager(); Employee emp2 = new Salesperson { SalesAmount = 50000 }; Console.WriteLine($"经理薪资:{emp1.CalculateSalary()}"); Console.WriteLine($"销售员薪资:{emp2.CalculateSalary()}"); } } }

image.png 说明

  • ManagerSalesperson 重写了 CalculateSalary() 方法,分别计算不同的薪资。
  • 使用基类引用调用方法,实现了对不同员工薪资的多态计算。

示例 5:模板方法模式

目标:通过方法重写实现模板方法模式。

C#
namespace App06 { public abstract class DataProcessor { // 模板方法 public void ProcessData() { ReadData(); Process(); SaveData(); } protected abstract void ReadData(); protected abstract void Process(); protected virtual void SaveData() { Console.WriteLine("数据已保存。"); } } public class ExcelDataProcessor : DataProcessor { protected override void ReadData() { Console.WriteLine("从 Excel 文件读取数据。"); } protected override void Process() { Console.WriteLine("处理 Excel 数据。"); } } public class CsvDataProcessor : DataProcessor { protected override void ReadData() { Console.WriteLine("从 CSV 文件读取数据。"); } protected override void Process() { Console.WriteLine("处理 CSV 数据。"); } protected override void SaveData() { Console.WriteLine("数据已保存到 CSV 文件。"); } } internal class Program { static void Main(string[] args) { // 使用示例 DataProcessor processor1 = new ExcelDataProcessor(); processor1.ProcessData(); DataProcessor processor2 = new CsvDataProcessor(); processor2.ProcessData(); } } }

image.png

说明

  • 基类 DataProcessor 定义了模板方法 ProcessData(),并声明了一些抽象方法。
  • 派生类实现了这些抽象方法,定制了具体的处理步骤。

注意事项

  • 方法签名一致:重写的方法必须与基类的方法具有相同的签名,包括方法名、参数类型和返回类型。
  • 访问修饰符:重写的方法的访问级别不能低于基类中被重写的方法。
  • sealed 关键字:如果不希望派生类进一步重写某个方法,可以在方法前添加 sealed 关键字。
C#
public override sealed void MethodName() { // 实现 }

总结

方法重写是实现多态性的关键,可以使代码更加灵活和可维护。通过在派生类中重写基类的方法,我们可以根据需要改变或扩展基类的行为,而无需修改基类的代码。在设计类的继承结构时,合理地使用方法重写,可以提高代码的质量和可扩展性。

建议

  • 在基类中,预期可能被修改的方法应声明为 virtualabstract
  • 在派生类中,重写方法时确保方法签名正确,并考虑是否需要调用 base 方法。
  • 谨慎使用方法重写,避免造成代码的混乱和难以维护。

希望通过本文的介绍,您能深入理解 C# 中的方法重写,并在实际编程中灵活应用。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!