C# 抽象类使用方法 C#如何定义和使用抽象类

来源:这里教程网 时间:2026-02-21 17:39:28 作者:

抽象类必须用
abstract
修饰,且不能被实例化

定义抽象类时,

class
前必须加
abstract
关键字,否则编译器会报错
CS0518: Predefined type 'System.Object' is not defined or imported
或更直接的
CS0144: Cannot create an instance of the abstract class or abstract method
。哪怕类里一个抽象成员都没有,只要标了
abstract
,就不能写
new MyAbstractClass()

常见误操作:

忘记加
abstract
却写了
abstract void DoSomething();
→ 编译失败,提示“包含抽象方法的类必须声明为
abstract
加了
abstract
却试图
new
它 → 运行前就报错,IDE 通常红色波浪线下划线
abstract
错写成
virtual
sealed
→ 语义完全错误,行为不可控

abstract
方法不能有方法体,子类必须用
override
实现

abstract
方法只声明签名,不提供实现,连大括号
{}
都不能有。子类继承后,必须用
public override
(或符合访问级别的
override
)给出具体逻辑,否则子类也得标
abstract

abstract class Animal
{
    public abstract void MakeSound(); // ✅ 正确:无实现
    // public abstract void Sleep() { } // ❌ 编译错误:abstract 方法不能有主体
}
<p>class Dog : Animal
{
public override void MakeSound() // ✅ 必须 override,且访问修饰符不能比基类更严格
{
Console.WriteLine("Woof!");
}
}

注意点:

abstract
方法默认是
public
,但显式写
public abstract
更清晰;不能用
private abstract
(编译器直接拒绝)
子类若没实现全部
abstract
成员,自身必须也声明为
abstract
abstract
方法不能是
static
virtual
sealed

抽象类可以含普通成员、
virtual
方法和构造函数

抽象类不是“空架子”,它可以像普通类一样拥有字段、属性、非抽象方法、

virtual
方法,甚至带参数的构造函数——这些都会被子类继承并可直接调用。

abstract class Shape
{
    protected string name;
<pre class='brush:php;toolbar:false;'>protected Shape(string name) => this.name = name; // ✅ 抽象类可以有构造函数
public abstract double GetArea(); // 子类必须实现
public virtual void Describe() => Console.WriteLine($"This is a {name}"); // ✅ 可被重写,也可直接调用
public void PrintType() => Console.WriteLine("Shape"); // ✅ 普通方法,子类自动继承

}

class Circle : Shape { private readonly double radius; public Circle(double r) : base("Circle") // ✅ 必须调用基类构造函数 { radius = r; }

public override double GetArea() => Math.PI * radius * radius;

}

关键细节:

子类构造函数必须通过
: base(...)
调用抽象基类的构造函数(如果有)
virtual
方法在抽象类中很常用:提供默认行为,允许子类选择性重写
字段和
protected
属性是子类共享状态的常用方式,但要注意封装边界

抽象类 vs 接口:选谁取决于“有没有共同状态或默认实现”

如果多个类型需要共享字段、构造逻辑、部分实现代码,或者你希望强制子类走某个初始化流程(比如必须传参进构造函数),就用抽象类。接口只描述“能做什么”,不提供状态或实现。

典型判断信号:

需要
protected
字段或
internal
辅助方法?→ 抽象类
想让子类自动获得一个
LogCreated()
默认日志行为?→ 抽象类 +
virtual
方法
只是约定一组行为(如
IDisposable
IComparable<t></t>
),且不同实现完全无关?→ 接口
一个类要同时满足多种契约(如既可比较又可序列化)?→ 必须用接口,因为 C# 不支持多继承

别为了“听起来高级”而硬套抽象类。很多初学者把所有基类都设成

abstract
,结果发现子类全得写重复构造逻辑,反而增加维护成本。

相关推荐