C# 中的抽象类

2025 年 9 月 6 日 | 阅读 8 分钟

C# 抽象类通过提供共享代码来定义其他类的模板并强制实现方法,从而提供了一种强大的方法。抽象类用于需要为类家族创建通用模板的情况,这允许派生类实现某些方法或属性。它们通常用于指定多个派生类共有的通用结构或行为,同时不阻止这些派生类提供其特定实现。

在 C# 中,抽象类是声明为抽象的类。它可以有抽象方法和非抽象方法。它包含多个字段、构造函数和方法。它不能直接实例化。它的实现必须由派生类提供。在这里,派生类被强制提供所有抽象方法的实现。

语法

它具有以下语法:

在这个语法中,

  • abstract class ClassName: 它表示抽象类的名称,这意味着它不能直接实例化。
  • return_type: 它表示抽象方法的返回类型。
  • NormalMethod: 它表示执行实现的身体。

C# 抽象类示例

让我们举一个例子来说明 C# 中的抽象类。

示例

编译并运行

输出

drawing rectangle...
drawing circle...

说明

在此示例中,我们声明了一个抽象类 `Shape`,其中包含一个抽象方法 `draw()`。之后,我们创建了 `Rectangle` 和 `Circle` 类,它们扩展了 `Shape` 并实现了各自的 `draw()`。在 `main()` 方法中,使用 `Shape` 引用在 `Rectangle` 和 `Circle` 对象上调用 `draw()`,这将打印出它们各自的消息。

带构造函数用于初始化的 C# 抽象类示例

让我们再举一个例子来说明使用构造函数的 C# 抽象类。

示例

编译并运行

输出

Name: Johnson
Salary: 25000
Name: Michael
Salary: 30000

说明

在此示例中,我们创建了一个 `Employee` 类作为基类,其中包含多个通用属性和方法。之后,我们创建了两个派生类 `Emp1` 和 `Emp2`,它们使用构造函数设置不同的名称和薪水,并重写抽象方法 `EmpName`。在运行时,显示员工的每个详细信息,这展示了抽象类的共享通用功能,同时允许特定的实现。

抽象方法

声明为抽象且没有主体的方法称为抽象方法。它只能在抽象类中声明。它的实现必须由派生类提供。

语法

它具有以下语法:

在这个语法中,

  • Access-modifier: 它表示抽象方法的可见性。
  • Abstract: 它用于将方法定义为抽象。
  • Return-type: 它用于定义方法应该返回的数据类型。
  • MethodName: 它表示抽象方法名称。

C# 中的抽象方法在内部是一个虚方法,因此它可以被派生类重写。我们不能在抽象方法声明中使用 `static` 和 `virtual` 修饰符。

C# 抽象方法示例

让我们举一个例子来说明 C# 中的抽象方法。

示例

编译并运行

输出

Cat says: Meow! Meow!
Cat is drinking milk.

说明

在此示例中,我们创建了一个抽象类 `Animal`,其中包含两个没有主体的抽象方法 `Speak()` 和 `Drink()`。之后,`Cat` 类继承自 `Animal` 并用其实现重写了这两个方法。在 `main()` 函数中,`Animal` 引用用于 `Cat` 对象,调用 `Speak()` 和 `Drink()` 会调用被重写的方法,从而演示了 `Cat` 的行为。

C# 银行账户详细信息抽象方法示例

让我们举一个例子来说明 C# 中银行账户详细信息的抽象方法。

示例

编译并运行

输出

600Rs deposited in Savings Account.
300Rs withdrawn from Savings Account.
Total Balance: 2100

说明

在此示例中,我们创建了一个抽象类,它定义了银行账户的结构,包含两个抽象方法 `Deposit` 和 `Withdraw`。之后,我们创建了一个派生类 `SavingsAcc`,它提供了这些方法的具体实现以处理存款和取款。在 `main` 方法中,我们创建了一个 `SavingsAcc` 类的对象,在该对象中我们进行交易并显示更新后的余额。

C# 中抽象类的用法

C# 中抽象类的几种用法如下:

  • 我们可以创建组件的多个版本,因为处理抽象类时版本控制不是问题。
  • 我们可以向抽象类添加属性或方法而无需重新编译,并且所有继承类都会自动更新更改。
  • 需要提供默认行为以及多个派生类将共有并能够重写的通用行为。

抽象类与接口的区别

C# 中抽象类和接口之间存在几个主要区别。一些主要区别如下:

特点抽象类Interface
定义抽象类是部分实现的类,它定义了类应该执行什么操作以及如何执行操作。接口是一个契约,它只定义方法签名、属性、事件和索引器,但没有实现。
实例化它不能被实例化。它不能被实例化。
访问修饰符它使用所有访问修饰符。它不使用访问修饰符,因为所有类默认都是公共的。
成员它包含多个字段、构造函数和方法。它只包含方法签名、事件、属性和索引器。
继承它只使用单继承。它可以实现多重继承。
实施它可以提供默认实现。它没有实现。

C# 中抽象类的优点

C# 中的抽象类有几个优点。其中一些如下:

  • 促进代码重用: 抽象类使我们能够指定可以由许多派生类共享的通用行为、方法和属性。
  • 充当派生类的模板: 它们是派生类的模板或蓝图。
  • 支持继承和多态: 抽象类允许多态,因此派生类可以被视为抽象类的实例。
  • 使用抽象方法指定契约: 抽象类使用抽象方法指定契约,这些方法由派生类实现。
  • 支持代码模块化和组织: 抽象类允许组织代码并支持模块化。
  • 允许将来的可扩展性: 抽象类旨在由派生类扩展。

C# 中抽象类的缺点

C# 中的抽象类有几个缺点。其中一些如下:

  • 紧密耦合: 抽象类在基抽象类及其子类之间引入了耦合元素。这意味着对抽象类的更改可能会影响所有子类。
  • 不完整实现: 抽象类通常包含抽象方法,这些方法需要在其派生类中实现。
  • 灵活性有限: 声明抽象类时,其结构和契约比接口的结构和契约更严格。
  • 面向对象设计问题: 在某些情况下,抽象类可能会破坏面向对象设计的一些原则,包括单一职责原则 (SRP) 或接口隔离原则 (ISP)。

结论

总之,C# 抽象类充当基模板,可以包含完全实现成员和没有主体的抽象成员。子类需要实现抽象成员。抽象类不能直接实例化,这使得它们非常适合提供通用功能,同时确保在子类中实现某些方法。

抽象类常见问题解答

1) 抽象类可以包含构造函数吗?

是的,抽象类可以包含构造函数。当创建派生类的对象以初始化基类成员时会调用它们。

2) 抽象类可以包含非抽象成员吗?

是的,它可以包含抽象(无主体)和非抽象(有主体)成员。它允许我们将通用实现与强制重写混合使用。

3) 什么时候应该使用抽象类而不是接口?

抽象类用于实现通用功能或提供可由派生类扩展的基本版本。另一方面,当我们只想定义功能契约而不实现任何内容时,接口非常有用。

4) 我们可以实例化抽象类的对象吗?

不,我们不能直接创建抽象类的实例。我们只能创建必须实现所有抽象成员的派生类的对象。

5) C# 中接口和抽象类有什么区别?

C# 中接口和抽象类的主要区别如下:

抽象类: 它可以包含已实现和抽象成员,支持字段,并允许访问修饰符。

接口: 它只有声明,没有字段,所有成员默认都是公共的。


下一个主题C# 接口