抽象类 (Abstract Class)
抽象类是 C# 面向对象编程中用于构建类层次结构的重要工具。它位于“普通类”和“接口”之间,既可以定义行为的标准(抽象方法),也可以提供通用的实现(普通方法)。
1. 核心概念与简介
抽象类是一种不能被实例化的类,它的主要作用是作为其他类的基类 (Base Class)。
- 关键字: ``abstract``
- 本质: 它定义了一个“框架”或“模版”。它告诉子类:“你必须拥有这些功能,但具体怎么做,由你自己决定。”
- 实例化: 绝对不能使用 ``new`` 关键字直接创建抽象类的对象(例如 ``new AbstractClass()`` 是非法的)。
2. 抽象方法 (Abstract Methods)
抽象方法是抽象类的核心特征。
* 语法特征:
- 必须使用 ``abstract`` 修饰。
- 没有方法体(即没有花括号 ``{}``,直接以分号 ``;`` 结束)。
- 只能存在于抽象类中。
* 实现规则:
- 任何继承了抽象类的非抽象子类,必须使用 ``override`` 关键字重写(实现)所有的抽象方法。
// 格式示例 abstract class Max // 抽象类 { // 抽象方法:只有定义,没有实现 public abstract void Run(); }
3. 案例分析与代码详解
以下代码展示了如何定义抽象类,以及如何在子类中实现它,并利用多态性进行调用。
using System; namespace AbstractDemo { class Program { static void Main(string[] args) { // 1. 实例化子类 // 抽象类不能 new,但子类可以 Test test = new Test(); test.Fangfa1(); // 调用子类重写后的方法 // 2. 抽象类的多态性 (核心知识点) // 虽然不能 new Chouxiang_class(),但可以声明该类型的变量 // 父类变量引用子类实例 Chouxiang_class test2 = test; test2.Fangfa1(); // 依然调用的是 Test 类中重写的逻辑 test2.num = 4; // 访问抽象类中定义的公共字段 Console.WriteLine($"Num value: {test2.num}"); } } // ==== 抽象类 (父类) ==== // 定义框架 abstract class Chouxiang_class { // 1. 抽象方法:强制子类必须实现 // 注意:没有方法体 {} public abstract void Fangfa1(); // 2. 普通字段:子类直接继承使用 public int num; // 3. 普通方法:抽象类也可以包含已实现的方法 public void CommonMethod() { Console.WriteLine("这是抽象类里的通用方法,子类可以直接用。"); } } // ==== 子类 ==== // 继承抽象类 class Test : Chouxiang_class { // 必须使用 override 关键字重写父类的抽象方法 public override void Fangfa1() { Console.WriteLine("子类 Test 已具体实现 Fangfa1 的逻辑"); } } }
4. 深度解析:为什么要用抽象类?
很多初学者会问:“为什么不直接写个普通父类,或者直接写个子类,非要搞个抽象类?”
- 强制性 (Enforcement):
如果你用普通父类定义一个空方法让子类去重写,子类可能会忘记重写。但使用 ``abstract``,编译器会强制子类必须重写,否则代码无法编译通过。这保证了所有子类都具备特定的行为。
- 代码复用 (Code Reuse):
抽象类不仅仅只有抽象方法,它还可以包含普通方法和字段(如上面的 ``num`` 字段)。这允许把所有子类共有的逻辑(比如日志记录、ID属性)放在父类中,避免重复代码。
- 多态 (Polymorphism):
如案例中的 ``Chouxiang_class test2 = test;``。我们可以用一个抽象的父类类型来管理一群不同的子类对象,这在工厂模式和插件开发中非常有用。
5. 易错点总结
* 错误 1: 试图实例化抽象类。
- ``Chouxiang_class a = new Chouxiang_class();`` → 报错。
* 错误 2: 抽象方法写了方法体。
- ``public abstract void Run() { }`` → 报错(不能有花括号)。
* 错误 3: 子类没有重写抽象方法。
- 如果子类继承了抽象类,却不实现其中的抽象方法,那么这个子类也必须被声明为 ``abstract``。
* 错误 4: 忘记写 ``override``。
- 在子类实现方法时,必须显式加上 ``override`` 关键字。
评论