====== 类的继承 (Class Inheritance) ======
类的继承是面向对象编程 (OOP) 的三大特性之一(封装、继承、多态)。它允许我们定义一个类(子类/派生类)来继承另一个类(父类/基类)的特性和行为。
===== 1. 基本语法与概念 =====
在 C# 中,继承使用冒号 ``:`` 符号。
**格式:**
class 子类名 : 父类名
{
// 子类特有的成员
}
**核心规则:**
* **单继承原则 (Single Inheritance):** 一个类只能直接继承**一个**父类(即 ``PS:单个类只能继承一个类!``)。但一个类可以实现多个接口。
* **继承的本质:** 子类会自动拥有父类中所有**非私有 (non-private)** 的成员(字段、属性、方法)。这实现了代码的复用。
* **传递性:** 如果 A 继承 B,B 继承 C,那么 A 同时拥有 B 和 C 的成员。
===== 2. 基础实例分析 =====
以下代码展示了如何通过继承共享属性 ``A``,同时子类各自拥有独立的成员。
using System;
namespace InheritanceDemo
{
class Program
{
static void Main(string[] args)
{
// 1. 实例化子类 wlala
wlala hei = new wlala();
// 2. 实例化子类 Bsei
Bsei kar = new Bsei();
// 3. 访问继承自父类 FB1 的属性 A
hei.A = 69; // wlala 本身没有定义 A,是继承来的
kar.A = 32; // Bsei 同理
// 4. 执行子类特有的方法
hei.beis(); // 输出: 69
// kar.beis(); // 报错:Bsei 类中没有 beis 方法
}
}
// ==== 父类 (基类) ====
class FB1
{
// 所有子类都会拥有的属性
public int A { get; set; }
}
// ==== 子类 1 ====
// wlala 继承了 FB1,所以它拥有 A
class wlala : FB1
{
public int B { get; set; } // 子类特有的属性
public void beis() // 子类特有的方法
{
// 可以直接访问父类的 A
Console.WriteLine("从父类继承的 A = {0}", A);
}
}
// ==== 子类 2 ====
class Bsei : FB1
{
public int C { get; set; }
}
}
===== 3. 继承的核心思想与多态 =====
继承不仅仅是为了少写代码,更重要的是为了实现**多态 (Polymorphism)** 和**里氏替换原则 (LSP)**。
==== 3.1 核心思想 1:复用 ====
* **子类可以使用父类成员:** 避免了在 ``wlala`` 和 ``Bsei`` 中重复定义属性 ``A``。修改父类的逻辑,所有子类都会自动更新。
==== 3.2 核心思想 2:多态与里氏替换 ====
* **概念:** 父类类型的变量可以引用子类的实例。
* **应用场景:** 工厂模式、依赖注入、统一处理集合。
**代码修正与深度解析:**
原笔记中的 ``public void shengcan();`` 是错误的语法。在类中,普通方法必须有方法体 ``{}``。如果想只定义规范而不实现,必须使用 ``abstract`` (抽象类) 或 ``interface`` (接口)。
以下是修正后的**工厂模式/多态**示例:
using System;
namespace FactoryPatternDemo
{
class Program
{
static void Main(string[] args)
{
// 声明一个父类变量 nb
NoteBook nb = null;
// 【多态的核心】:父类变量指向子类对象
// 无论 new 出来的是 Lenovo 还是 IBM,它们都是 NoteBook
nb = new Lenovo();
nb.ShengCan(); // 调用的是 Lenovo 的生产逻辑
nb = new IBM();
nb.ShengCan(); // 调用的是 IBM 的生产逻辑
// 实际应用中,这里通常配合简单工厂模式:
// NoteBook myComputer = ComputerFactory.Create("Lenovo");
}
}
// 建议将父类定义为 abstract (抽象类),因为单纯的 "笔记本" 概念无法生产,
// 只有具体的品牌才能生产。
public abstract class NoteBook
{
// 抽象方法:强制子类必须实现这个方法
public abstract void ShengCan();
}
// 以下类继承了 NoteBook 父类
public class Lenovo : NoteBook
{
public override void ShengCan()
{
Console.WriteLine("联想笔记本正在生产...");
}
}
public class IBM : NoteBook
{
public override void ShengCan()
{
Console.WriteLine("IBM ThinkPad 正在生产...");
}
}
public class Weixing : NoteBook // 微星
{
public override void ShengCan()
{
Console.WriteLine("微星游戏本正在生产...");
}
}
public class DeLL : NoteBook
{
public override void ShengCan()
{
Console.WriteLine("戴尔笔记本正在生产...");
}
}
}
===== 4. 知识点扩展 (Deep Dive) =====
为了更深入理解继承,需要注意以下几点:
- **访问修饰符 (Access Modifiers):**
* ``public``: 子类和外部都能访问。
* ``private``: 只有父类自己能访问,**子类无法直接访问**(虽然继承了,但不可见)。
* ``protected``: **关键修饰符**。只有父类和**子类**可以访问,外部无法访问。
- **构造函数 (Constructors):**
* 构造函数**不会**被继承。
* 实例化子类时,会**先执行父类的构造函数**,再执行子类的构造函数。
* 如果父类构造函数需要参数,子类必须使用 ``: base(参数)`` 显式调用。
- **Object 类:**
* 在 C# 中,所有的类都隐式继承自 ``System.Object`` 类。因此所有类都有 ``ToString()``, ``Equals()`` 等方法。