商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C#怎么使用抽象类abstract_C#抽象类和抽象方法教程【进阶】

C#怎么使用抽象类abstract_C#抽象类和抽象方法教程【进阶】

  发布于2026-07-18 阅读(0)

扫一扫,手机访问

抽象类在C#中的地位有些特殊——它不能直接实例化,只允许被继承。换句话说,只要一个类里出现了abstract标识的方法,这个类就必须声明为abstract class,否则编译器会直接报错。这可不是什么小细节,而是整个抽象机制的设计起点。

先搞清楚一个基本规则:abstract class是不能用new来创建实例的。想试试new Animal()?编译器会直接甩你一脸CS0144:“无法创建抽象类的实例”。抽象类存在唯一的意义,就是作为基类被继承。它允许你定义一部分可复用的逻辑(比如Sleep()),同时强制子类实现关键行为(比如MakeSound())。

具体来说,抽象类有几个值得注意的特性:

  • 抽象类可以有构造函数,子类初始化时会自动调用它(哪怕你不写base()
  • 抽象类可以包含字段、属性、普通方法、静态成员,甚至protectedinternal成员
  • 但不能用sealed修饰抽象类——这俩语义冲突:一个要求必须被继承,一个禁止被继承

抽象方法:只有契约,没有实现

抽象方法的声明形式是public abstract void Run();,结尾是分号,没有{}。它不提供任何实现,只划出契约边界。一旦父类中存在这样的方法,所有非抽象子类都必须用override显式实现它。

这里有几点必须注意:

  • 不能加private——子类根本访问不到,还怎么重写?
  • 不能加staticvirtual——abstract已隐含virtual语义,二者重复;static属于类型而非实例,和“由子类实现”的设计目标矛盾
  • 抽象方法可以是protected,但不推荐:外部无法通过变量调用,削弱了多态价值

什么时候选抽象类,什么时候选接口

这是个经典问题。当你要共享代码实现、需要字段或构造逻辑、或者想约束继承链深度(只能单继承)时,优先考虑抽象类。举个例子,所有Shape都要记录CreatedTime字段,都有默认的ToString()实现,但面积计算必须由子类决定——这种场景抽象类再合适不过。

对比来看:

  • 接口更适合定义“能做什么”(IComparableIDisposable),抽象类更适合定义“是什么+部分怎么做”(StreamException
  • C# 8.0+支持接口默认方法,但接口仍不能有字段或构造器,这点和抽象类有本质区别
  • 一个类可以: Animal, IFlyable, ISwimmable,但只能: Mammal——继承结构越清晰,越该用抽象类做骨架

一个容易被忽略的细节:抽象类可以没有抽象方法

很多人在这里卡壳。比如abstract class Logger完全可以不写任何abstract方法,只提供通用日志格式化逻辑,并用abstract修饰自身来防止被误实例化。编译器只检查“有没有abstract成员”来决定是否强制子类实现,不检查“有没有abstract方法”。

还有几点补充:

  • 反过来,只要有一个abstract方法,类就必须是abstract——没得商量
  • 抽象子类可以不实现父类的抽象方法,但再下一级非抽象子类必须补全
  • 抽象类的构造函数不能是abstract,但它可以是protected,这是最常见也最合理的做法

C#怎么使用抽象类abstract_C#抽象类和抽象方法教程【进阶】

本文转载于:https://www.php.cn/faq/2343968.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注