0

0

c# 继承和多态详解

月夜之吻

月夜之吻

发布时间:2026-01-23 09:11:29

|

255人浏览过

|

来源于php中文网

原创

继承是多态的结构基础,多态是继承的行为表现;abstract用于父类只定义契约不实现时,virtual用于提供默认行为且允许覆盖;多态仅在父类引用调用虚/抽象方法时生效。

c# 继承和多态详解

继承和多态不是两个独立概念,而是一体两面:继承是结构基础,多态是行为表现——没继承,多态无从谈起;没抽象或虚成员,多态就只是普通调用。

什么时候必须用 abstract

当你在父类中「只定义行为契约,不提供实现」时,就必须用 abstract。比如所有动物都要 MakeSound(),但狗叫、猫叫、鸟鸣各不相同,父类无法写死逻辑。

  • 抽象方法必须放在 abstract class 中,且子类非抽象时,override 是强制的
  • 抽象类可以没有抽象方法(比如只做类型约束或共享字段)
  • 不能 new 抽象类实例,哪怕它有构造函数
  • 错误现象:'Animal' does not implement inherited abstract member 'Animal.MakeSound()' —— 子类忘了加 override 或漏了方法体

什么时候该用 virtual 而不是 abstract

当父类能提供一个「合理默认行为」,但允许子类按需覆盖时,用 virtual。比如 ToString() 默认返回类型名,子类可重写为返回更友好的格式。

  • 虚方法可以被子类 override,也可以不重写,直接沿用父类逻辑
  • 子类中若想调用父类原版实现,得显式写 base.MethodName()
  • 常见误用:把本该是 virtual 的方法写成 privatesealed,导致子类无法扩展
  • 性能影响极小,但过度虚化(比如每个 getter 都 virtual)会轻微增加虚表查找开销,一般无需担心

多态真正生效的两个典型场景

多态不是“写了 override 就自动多态”,它只在「通过父类引用调用虚/抽象方法」时才触发。关键看变量声明类型,不是实际对象类型。

Inworld.ai
Inworld.ai

InWorldAI是一个AI角色开发平台,开发者可以创建具有自然语言、上下文意识和多模态的AI角色,并可以继承到游戏和实时媒体中

下载
Animal a1 = new Dog();
Animal a2 = new Cat();
Console.WriteLine(a1.MakeSound()); // 输出 "Woof!"
Console.WriteLine(a2.MakeSound()); // 输出 "Meow!"
  • 参数多态:void Feed(Animal animal) { animal.Eat(); } —— 传 Dog 就执行 Dog.Eat(),传 Bird 就执行 Bird.Eat()
  • 返回值多态:Animal Create(string type) => type switch { "dog" => new Dog(), "cat" => new Cat() }; —— 调用方只需按 Animal 处理,不用关心具体类型
  • 容易踩的坑:用子类变量直接调用,比如 Dog d = new Dog(); d.MakeSound(); —— 这走的是静态绑定,不触发多态,哪怕方法是 virtualabstract
  • 注意:只有 virtualabstractoverride 成员参与多态;privatestaticsealed override 均不参与

protectedbase 在继承链中的真实作用

protected 不是“给子类用的 public”,而是「仅限派生类内部访问」的访问修饰符;base 是子类访问父类成员的唯一安全通道。

  • protected 成员可在子类中直接使用(如 this.Name),但不能通过子类实例访问(new Dog().Name 报错)
  • 子类构造函数必须显式或隐式调用基类构造函数;若基类无无参构造,子类必须用 : base(...) 指定
  • 常见错误:base 调用位置不对(必须是构造函数第一行)、或在静态方法里误用 base
  • 不要用 protected 暴露内部状态,优先考虑 protected virtual 方法供子类定制行为,而非暴露字段

最常被忽略的一点:多态依赖运行时类型信息(RTTI),而 .NET 的 JIT 编译器对虚调用做了高度优化,所以别因“怕慢”而回避 virtual —— 真正的性能瓶颈几乎从来不在这里,而在设计失当导致的深层继承链或过度抽象。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

338

2023.08.02

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

534

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

418

2024.03.13

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

15

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

15

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

15

2025.11.27

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

175

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

98

2025.11.27

菜鸟裹裹入口以及教程汇总
菜鸟裹裹入口以及教程汇总

本专题整合了菜鸟裹裹入口地址及教程分享,阅读专题下面的文章了解更多详细内容。

0

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP基础入门课程
PHP基础入门课程

共33课时 | 2万人学习

前端系列快速入门课程
前端系列快速入门课程

共4课时 | 0.4万人学习

C# 教程
C# 教程

共94课时 | 7.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号