CodeGym /课程 /C# SELF /构建层级结构中的抽象

构建层级结构中的抽象

C# SELF
第 22 级 , 课程 3
可用

1. 引言

咱们试着从高处看看抽象:想象一个大办公室,不同员工做着不同的事。他们可能有个共同的职位——"员工",但每个人有自己的任务。可如果你是老板,只想让每个员工都能"完成工作",你根本不用关心他们怎么做:程序员写代码,会计打报表。这种“所有人都遵守的通用契约,细节交给专业的人”就是合理构建类层级的核心思想。

代码里长啥样?

一切都从基础的抽象类开始。它描述了所有子类必须会的最重要的东西。


public abstract class Employee
{
    public string Name { get; }
    public Employee(string name)
    {
        Name = name;
    }

    // 抽象方法——所有员工的契约
    public abstract void DoWork();
}

接下来是派生类(子类)——程序员和会计:


public class Programmer : Employee
{
    public Programmer(string name) : base(name) { }
    public override void DoWork()
    {
        Console.WriteLine($"{Name} 写代码");
    }
}

public class Accountant : Employee
{
    public Accountant(string name) : base(name) { }
    public override void DoWork()
    {
        Console.WriteLine($"{Name} 算钱");
    }
}

注意啦:我们可以创建一个员工列表——不管是会计还是程序员,甚至你想加啥都行(抽象完全支持你这么干!)。


Employee[] office = new Employee[]
{
    new Programmer("瓦夏"),
    new Accountant("塔尼娅")
};

foreach (Employee emp in office)
{
    emp.DoWork(); // 每个人做自己的事
}

瓦夏 写代码
塔尼娅 算钱

你看,现在多优雅、多通用,最重要的是可扩展。你想加个新类,比如Manager,原来的代码根本不用动!

2. 如何用抽象构建层级结构

几乎每本OOP教材都离不开动物的例子,咱们也来一波。

抽象类——“大Boss”


public abstract class Animal
{
    public string Name { get; set; }
    public Animal(string name)
    {
        Name = name;
    }

    // 所有动物都得会发出声音
    public abstract void MakeSound();

    // 但不是每个都能飞,所以:
    public virtual void Fly()
    {
        Console.WriteLine("我不会飞。");
    }
}

子类:必须会叫,也可以重写别的方法


public class Cat : Animal
{
    public Cat(string name) : base(name) { }
    public override void MakeSound()
    {
        Console.WriteLine($"{Name}: 喵!");
    }
}

public class Dog : Animal
{
    public Dog(string name) : base(name) { }
    public override void MakeSound()
    {
        Console.WriteLine($"{Name}: 汪!");
    }
}

public class Eagle : Animal
{
    public Eagle(string name) : base(name) { }
    public override void MakeSound()
    {
        Console.WriteLine($"{Name}: 啸叫!");
    }

    public override void Fly()
    {
        Console.WriteLine($"{Name} 在天上飞!");
    }
}

来,组个动物园集合试试:


Animal[] zoo = new Animal[]
{
    new Cat("巴尔西克"),
    new Dog("沙里克"),
    new Eagle("奥廖尔")
};

foreach (Animal animal in zoo)
{
    animal.MakeSound();
    animal.Fly();
}

巴尔西克: 喵!
我不会飞。
沙里克: 汪!
我不会飞。
奥廖尔: 啸叫!
奥廖尔 在天上飞!

你看,用啥子类都超简单:根本不用管集合里到底是啥对象。抽象负责“契约”,具体行为交给实现。

3. 多层抽象

抽象不只是基础类和直接子类的事。在复杂系统里,抽象经常分好几层,一个抽象类还能继承另一个。这就像千层蛋糕(或者像史莱克说的洋葱):每一层都藏掉不必要的细节,只留你关心的。

例子:交通工具的层级结构


.              Vehicle (abstract)
            /           |           \
       Car           Airplane      Boat
  ElectricCar    JetAirplane    SailBoat

这里Vehicle定义了通用原则(比如Move()方法),但它不知道车和飞机怎么动,这得子类来定。更具体的类,比如ElectricCarJetAirplane,还能加自己的细节,扩展功能。

层级结构的流程图:


.       +------------------+
        |  Vehicle         |  <--- 抽象类
        +------------------+
        /        \
   +-------+   +-------+
   |  Car  |   | Boat  |  <--- 中间抽象或具体类
   +-------+   +-------+

代码:基础抽象类


public abstract class Vehicle
{
    public string Model { get; }
    public Vehicle(string model)
    {
        Model = model;
    }

    // 抽象方法
    public abstract void Move();
}

中间抽象类

有时候中间层也得有自己的抽象!


public abstract class Car : Vehicle
{
    public Car(string model) : base(model) { }

    public override void Move()
    {
        Console.WriteLine($"{Model} 在路上跑。");
    }

    // 抽象方法——不是每辆车都用电:
    public abstract void RefuelOrCharge();
}

具体实现


public class ElectricCar : Car
{
    public ElectricCar(string model) : base(model) { }

    public override void RefuelOrCharge()
    {
        Console.WriteLine($"{Model} 正在充电。");
    }
}

public class GasolineCar : Car
{
    public GasolineCar(string model) : base(model) { }

    public override void RefuelOrCharge()
    {
        Console.WriteLine($"{Model} 加汽油。");
    }
}

结果:多层抽象让你加新类和新功能都很轻松。

可视化:类层级结构示例

类型 抽象 父类 特殊行为
Vehicle 基础 - 抽象方法 Move()
Car 中间 Vehicle 抽象 RefuelOrCharge()
ElectricCar 最终 Car 实现 RefuelOrCharge()
GasolineCar 最终 Car 实现 RefuelOrCharge()
Boat 最终 Vehicle 实现 Move()

4. 用抽象打造可扩展应用

实际好处:

  1. 代码灵活、可扩展:你可以加新类(比如新动物、新交通工具或新员工),不用改现有代码。你的循环/方法会自动支持新对象——只要它实现了抽象里定义的方法。
  2. 减少代码重复:通用属性和方法(比如名字、基础逻辑)只在抽象类里写一次,子类自动继承。
  3. 大型框架和系统常用:比如ASP.NET MVC有抽象的基础控制器(ControllerBase),WinForms有所有UI控件的抽象类Control。这样扩展框架时不会破坏已有部分。

哪里用得上?

  • 各种大型系统:银行应用(员工、操作和交易)、游戏(游戏实体、角色)、商业应用(目录、商品、用户)、任何有层级和结构化数据的地方。
  • 技术面试:会用抽象构建类、能讲清楚层级结构——面试常考。
  • 程序架构:抽象让你在写逻辑前就能搭好“骨架”——方便团队开发、TDD(测试驱动开发)和后期维护。

5. 构建层级结构时的常见坑

错误1:忘了实现抽象方法。
如果你没实现基类的所有抽象成员,编译器绝对不让你创建子类实例。这是硬性规定——想变具体,必须全都实现。

错误2:想多继承抽象类。
C#不支持多继承,就算全是抽象类也不行。这是语言限制。如果你想“继承”多个来源的行为——用接口吧。接口就像抽象类,但更轻,没有实现。

错误3:没搞懂中间抽象类的意义。
这种类常用来归纳通用逻辑,防止创建“没定义全”的对象。比如Car可以是抽象的,这样没人能直接创建“车”,必须明确是汽油的、柴油的还是电的。

2
任务
C# SELF, 第 22 级, 课程 3
已锁定
创建带有抽象类的类层次结构
创建带有抽象类的类层次结构
2
任务
C# SELF, 第 22 级, 课程 3
已锁定
多层抽象:交通工具
多层抽象:交通工具
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION