====== 抽象类 (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`` 关键字。