当前位置: 首页 > news >正文

C# 基础——多态的实现方式

在C#中,多态(Polymorphism)是面向对象编程的核心特性之一,指“同一操作作用于不同对象时,可产生不同的执行结果”。其本质是通过统一的接口(或基类)调用不同实现,实现代码的灵活性和可扩展性。

C#中多态的实现方式主要有以下4种,核心是基于动态绑定(运行时确定具体调用的方法)静态绑定(编译时确定)

1. 继承+虚方法重写(virtual + override)

这是最常用的动态多态实现方式,通过基类定义虚方法,派生类重写该方法,最终通过基类引用调用时,会自动执行派生类的实现。

实现步骤:
  • 基类中用 virtual 关键字声明方法(含默认实现);
  • 派生类中用 override 关键字重写该方法(提供自定义实现);
  • 通过基类引用指向派生类对象,调用方法时自动执行派生类的重写版本。
示例代码:
// 基类
public class Animal {// 虚方法:定义统一接口,提供默认实现public virtual void Speak() {Console.WriteLine("动物发出声音");}
}// 派生类1:重写虚方法
public class Dog : Animal {public override void Speak() {Console.WriteLine("狗叫:汪汪");}
}// 派生类2:重写虚方法
public class Cat : Animal {public override void Speak() {Console.WriteLine("猫叫:喵喵");}
}// 调用:多态体现
class Program {static void Main() {Animal animal1 = new Dog(); // 基类引用指向派生类对象Animal animal2 = new Cat();animal1.Speak(); // 输出:狗叫:汪汪(执行Dog的实现)animal2.Speak(); // 输出:猫叫:喵喵(执行Cat的实现)}
}
特点:
  • 动态绑定:运行时根据对象实际类型确定调用的方法;
  • 基类有默认实现,派生类可选择是否重写(不重写则沿用基类逻辑)。

2. 抽象类+抽象方法(abstract)

抽象类是无法实例化的基类,其中的抽象方法(abstract没有默认实现,必须由派生类强制重写。通过抽象类引用调用方法时,同样会执行派生类的实现,属于动态多态。

实现步骤:
  • abstract 关键字定义抽象类;
  • 抽象类中用 abstract 声明抽象方法(只有签名,无方法体);
  • 派生类必须用 override 重写所有抽象方法;
  • 通过抽象类引用指向派生类对象,调用方法时执行派生类实现。
示例代码:
// 抽象基类(无法实例化)
public abstract class Shape {// 抽象方法:必须由派生类实现public abstract double GetArea();
}// 派生类1:实现抽象方法
public class Circle : Shape {public double Radius { get; set; }public Circle(double radius) => Radius = radius;public override double GetArea() {return Math.PI * Radius * Radius; // 圆面积公式}
}// 派生类2:实现抽象方法
public class Rectangle : Shape {public double Width { get; set; }public double Height { get; set; }public Rectangle(double w, double h) {Width = w;Height = h;}public override double GetArea() {return Width * Height; // 矩形面积公式}
}// 调用:多态体现
class Program {static void Main() {Shape shape1 = new Circle(2); // 抽象类引用指向派生类Shape shape2 = new Rectangle(3, 4);Console.WriteLine(shape1.GetArea()); // 输出:12.566...(圆面积)Console.WriteLine(shape2.GetArea()); // 输出:12(矩形面积)}
}
特点:
  • 动态绑定:运行时确定调用的方法;
  • 强制派生类实现抽象方法(避免“忘记重写”的错误);
  • 抽象类可包含非抽象方法(提供默认实现)。

3. 接口实现(interface)

接口是一种“行为契约”,仅定义方法签名(无实现),类通过 implements 关键字实现接口时,必须实现接口的所有方法。不同类可实现同一接口的不同逻辑,通过接口引用调用时体现多态。

实现步骤:
  • interface 关键字定义接口(方法无访问修饰符,默认public);
  • 类用 : 接口名 实现接口,并实现所有接口方法;
  • 通过接口引用指向实现类对象,调用方法时执行对应类的实现。
示例代码:
// 接口:定义行为契约
public interface IFlyable {void Fly(); // 仅声明,无实现
}// 实现类1:鸟
public class Bird : IFlyable {public void Fly() {Console.WriteLine("鸟扇动翅膀飞行");}
}// 实现类2:飞机
public class Plane : IFlyable {public void Fly() {Console.WriteLine("飞机靠引擎飞行");}
}// 调用:多态体现
class Program {static void Main() {IFlyable flyer1 = new Bird(); // 接口引用指向实现类IFlyable flyer2 = new Plane();flyer1.Fly(); // 输出:鸟扇动翅膀飞行flyer2.Fly(); // 输出:飞机靠引擎飞行}
}
特点:
  • 动态绑定:运行时确定调用的方法;
  • 接口支持“多实现”(一个类可实现多个接口),而类只能单继承,因此接口更灵活;
  • 适合定义跨类别的通用行为(如“飞行”可被鸟、飞机等不同类型的类实现)。

4. 隐藏基类方法(new关键字)

通过 new 关键字在派生类中定义与基类同名的方法,会“隐藏”基类方法(而非重写)。这种方式属于静态多态(编译时绑定),调用哪个版本的方法由“引用类型”而非“对象实际类型”决定。

实现步骤:
  • 基类定义普通方法;
  • 派生类用 new 关键字定义同名方法(隐藏基类方法);
  • 调用时,基类引用调用基类方法,派生类引用调用派生类方法。
示例代码:
public class Parent {public void Print() {Console.WriteLine("父类方法");}
}public class Child : Parent {// new关键字:隐藏父类的Print方法public new void Print() {Console.WriteLine("子类方法");}
}class Program {static void Main() {Parent p = new Child(); // 基类引用指向派生类对象Child c = new Child();  // 派生类引用p.Print(); // 输出:父类方法(由引用类型Parent决定)c.Print(); // 输出:子类方法(由引用类型Child决定)}
}
注意:
  • 这不是“真正的多态”,因为行为由引用类型(编译时已知)决定,而非对象实际类型;
  • 通常不推荐使用,容易导致逻辑混淆(建议优先用 override 重写)。

总结:多态实现方式的对比

方式核心关键字绑定时机适用场景
虚方法重写virtual + override运行时基类有默认实现,派生类可选择性重写
抽象类+抽象方法abstract + override运行时基类无默认实现,强制派生类提供具体逻辑
接口实现interface运行时跨类别的行为约定,支持多实现
隐藏基类方法new编译时特殊场景(不推荐,易混淆)

实际开发中,接口实现虚方法重写是最常用的多态方式,它们通过动态绑定实现了“统一接口,不同实现”,大幅提升了代码的扩展性和可维护性。

http://www.dtcms.com/a/508033.html

相关文章:

  • 【Nginx反向代理技术详解】原理、配置与实践
  • 福州企业网站维护价格低网站建设人员的安排
  • icon图标素材下载网站网络营销推广策划的步骤
  • ObjectId objectId = gridFSTemplate.store(fileInputStream, “文件轮播对象“, ““)
  • SpringBoot的actuator组件快速使用
  • STM32学习(MCU控制)(GPIO)
  • wordpress站点标题添加如何注册一个自己的公司
  • 台州企业网站搭建价格网站开发的交付文档
  • 橙色守护者:嘉顺达蓝海的危险品运输安全密码
  • 安全监控摄像头通过智能组网模块实现联网报警和远程管理的实践解析
  • AI时代的数据管理新范式:Git for Data让数据工程化
  • Linux中内核调用用户空间程序的实现
  • 建网站空间的详细说明网站备案怎么查询
  • 2025 兽用 mRNA 疫苗市场调研:58.7% CAGR 下,技术路线与投资前景深度分析
  • 关于 Qt5.x版本离线安装可以跳过登录但是实际离线仍需要登录 的解决方法
  • 什么时候会出现电源平面谐振?
  • php做网站常见实例新市网站建设
  • 【Vue知识点总结】style标签的 scoped 属性
  • 网站移动适配怎么做济南做网站互联网公司排名
  • authui!CLogonFrame::Create中的USER32!LoadImageW可以作为有效起始断点
  • Linux服务器编程实践50-TCP接收与发送缓冲区:SO_RCVBUF与SO_SNDBUF设置
  • 免费无版权图片素材网站中国制造网简介
  • 鸿蒙Next Test Kit:一站式自动化测试框架详解
  • 《微信小程序》第一章:开发前准备与配置
  • 实验二-决策树-葡萄酒
  • 用双语网站做seo会不会建设一个网站需要哪些员工
  • 专项智能练习(教学过程的规律)
  • 设计模式-创建型设计模式
  • 非关系型数据库(NoSQL)学习指南:从入门到实战
  • Endnote | word中参考文献段落对齐及悬挂缩进的设置