多态的核心是:
同一个接口(方法名),不同对象有不同实现。
而 抽象类实现多态,就是 C# 提供的一种“强制子类实现”多态的机制。 我们一步步来理解 👇
🧩 一、什么是抽象类(abstract class)
在 C# 中:
抽象类(abstract class) 是不能被实例化的类。
它是为了被继承而存在的。
它里面可以包含:
抽象方法(abstract method) → 没有方法体,必须由子类实现;
普通方法 → 可以直接使用;
属性、字段、构造函数 等。
🧠 二、为什么抽象类能实现多态?
因为“抽象方法”规定了一个统一的接口, 不同子类必须提供自己的具体实现。
于是我们就可以在运行时, 通过父类引用调用不同子类的实现 —— 这就是 运行时多态。
💻 三、简单示例:抽象类实现多态
using System;
abstract class Animal
{
// 抽象方法:没有方法体,子类必须重写
public abstract void Speak();
}
class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("狗在汪汪叫。");
}
}
class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("猫在喵喵叫。");
}
}
class Program
{
static void Main()
{
Animal a1 = new Dog();
Animal a2 = new Cat();
a1.Speak(); // 输出:狗在汪汪叫。
a2.Speak(); // 输出:猫在喵喵叫。
}
}
🔍 运行分析:
Animal
定义了一个“统一的接口”Speak()
;Dog
和Cat
必须实现它;运行时,根据
a1
、a2
的真实类型(Dog / Cat),执行各自的方法;结果就是:同一方法,不同表现 → 多态。
🧩 四、与 virtual 的区别
✅ 简单记忆:
virtual:父类有默认实现,子类可重写。 abstract:父类不给实现,子类必须重写。
🧱 五、抽象类多态的典型应用场景
这些都有一个共同点: 父类定义“应该做什么”,子类定义“具体怎么做”。
✅ 六、总结一句话
抽象类实现多态: 通过在抽象类中定义抽象方法,让不同子类必须实现该方法, 从而在运行时通过父类引用调用不同子类的实现。
💬 换句话说:
抽象类规定“所有子类都必须会说话”, 但“怎么说”由每个子类自己决定。😄
是否希望我帮你画一张「抽象类实现多态」的结构图? (显示 Animal → Dog/Cat
的继承关系和方法调用方向,非常适合教学或视频讲解用。)
八、练习题
练习1:计算器程序
public abstract class 运算
{
public abstract double 计算(double a, double b);
}
public class 加法 : 运算
{
public override double 计算(double a, double b)
{
return a + b;
}
}
public class 乘法 : 运算
{
public override double 计算(double a, double b)
{
return a * b;
}
}
// 使用多态的计算器
运算 当前运算 = new 加法();
double 结果 = 当前运算.计算(5, 3); // 8
当前运算 = new 乘法();
结果 = 当前运算.计算(5, 3); // 15
练习2:游戏角色系统
public abstract class 游戏角色
{
public string 名字;
public abstract void 攻击();
}
public class 战士 : 游戏角色
{
public override void 攻击()
{
Console.WriteLine($"{名字}用剑砍击!");
}
}
public class 法师 : 游戏角色
{
public override void 攻击()
{
Console.WriteLine($"{名字}发射火球!");
}
}
public class 弓箭手 : 游戏角色
{
public override void 攻击()
{
Console.WriteLine($"{名字}射出弓箭!");
}
}
// 在游戏中使用
游戏角色[] 队伍 = new 游戏角色[]
{
new 战士() { 名字 = "勇者" },
new 法师() { 名字 = "魔法师" },
new 弓箭手() { 名字 = "神射手" }
};
foreach (游戏角色 角色 in 队伍)
{
角色.攻击(); // 每个角色用自己的方式攻击
}
##