专栏导航
- ← 上一篇:面向对象进阶 - 接口
- ← 第一篇:编程世界初探
- 专栏目录
在前几章中,我们学习了继承、抽象类和接口。这一周,我们将探索面向对象编程中最重要也是最难理解的概念——多态。多态让我们的代码更加灵活、可扩展。
一、什么是多态?
1.1 现实生活中的多态
想象一下:
一个"发出声音"的指令
├── 狗 → 汪汪
├── 猫 → 喵喵
├── 鸟 → 叽叽喳喳
└── 牛 → 哞哞
同样的指令,不同的对象有不同的反应,这就是多态。
1.2 编程中的多态
多态(Polymorphism)是面向对象编程的三大特性之一。它允许使用统一的接口处理不同类型的对象,这些对象会根据自身的类型做出不同的响应。
Animal animal = new Dog(); // 父类引用指向子类对象
animal.MakeSound(); // 调用 Dog 的方法
1.3 多态的好处
好处:
✅ 代码复用:同一套代码处理不同类型
✅ 灵活扩展:新增类型无需修改现有代码
✅ 解耦合:降低代码之间的依赖
✅ 易于维护:代码结构清晰
二、多态的实现方式
2.1 三种实现多态的方式
| 方式 | 关键字 | 说明 |
|---|---|---|
| 方法重载 | 同类中同名不同参数 | 编译时多态 |
| 方法重写 | virtual/override | 运行时多态 |
| 接口实现 | 接口多态 | 运行时多态 |
2.2 多态流程图
父类引用 → 指向子类对象
↓
调用方法
↓
运行时判断对象实际类型
↓
调用对应类型的实现
↓
多态效果
三、方法重载(编译时多态)
3.1 什么是方法重载?
方法重载是指在同一个类中,定义多个同名方法,但参数列表不同。
3.2 示例
using System;
namespace Week12Practice
{
class Calculator
{
// 重载1:两个整数相加
public int Add(int a, int b)
{
return a + b;
}
// 重载2:三个整数相加
public int Add(int a, int b, int c)
{
return a + b + c;
}
// 重载3:两个 double 相加
public double Add(double a, double b)
{
return a + b;
}
// 重载4:字符串连接
public string Add(string a, string b)
{
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 方法重载示例 =====\n");
Calculator calc = new Calculator();
Console.WriteLine($"10 + 20 = {calc.Add(10, 20)}");
Console.WriteLine($"10 + 20 + 30 = {calc.Add(10, 20, 30)}");
Console.WriteLine($"10.5 + 20.5 = {calc.Add(10.5, 20.5)}");
Console.WriteLine($"Hello + World = {calc.Add("Hello", "World")}");
}
}
}
输出:
===== 方法重载示例 =====
10 + 20 = 30
10 + 20 + 30 = 60
10.5 + 20.5 = 31
Hello + World = HelloWorld
四、方法重写(运行时多态)
4.1 virtual 和 override
使用 virtual 和 override 关键字实现方法重写。
class Parent
{
public virtual void Method()
{
Console.WriteLine("父类方法");
}
}
class Child : Parent
{
public override void Method()
{
Console.WriteLine("子类方法");
}
}
4.2 完整示例
using System;
namespace Week12Practice
{
// 基类:动物
class Animal
{
public string Name { get; set; }
// 虚方法:可以被重写
public virtual void MakeSound()
{
Console.WriteLine($"{Name} 发出声音");
}
public virtual void Eat()
{
Console.WriteLine($"{Name} 正在吃东西");
}
}
// 派生类:狗
class Dog : Animal
{
public Dog(string name)
{
Name = name;
}
// 重写方法
public override void MakeSound()
{
Console.WriteLine($"{Name}: 汪汪汪!");
}
public override void Eat()
{
Console.WriteLine($"{Name} 正在啃骨头");
}
}
// 派生类:猫
class Cat : Animal
{
public Cat(string name)
{
Name = name;
}
public override void MakeSound()
{
Console.WriteLine($"{Name}: 喵喵喵!");
}
public override void Eat()
{
Console.WriteLine($"{Name} 正在吃鱼");
}
}
// 派生类:牛
class Cow : Animal
{
public Cow(string name)
{
Name = name;
}
public override void MakeSound()
{
Console.WriteLine($"{Name}: 哞哞哞!");
}
public override void Eat()
{
Console.WriteLine($"{Name} 正在吃草");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 方法重写示例 =====\n");
// 使用父类引用指向子类对象
Animal[] animals = new Animal[]
{
new Dog("旺财"),
new Cat("咪咪"),
new Cow("奶牛"),
new Dog("大黄")
};
Console.WriteLine("--- 多态调用 ---");
foreach (Animal animal in animals)
{
animal.MakeSound(); // 多态:调用各自的重写方法
animal.Eat();
Console.WriteLine();
}
}
}
}
输出:
===== 方法重写示例 =====
--- 多态调用 ---
旺财: 汪汪汪!
旺财 正在啃骨头
咪咪: 喵喵喵!
咪咪 正在吃鱼
奶牛: 哞哞哞!
奶牛 正在吃草
大黄: 汪汪汪!
大黄 正在啃骨头
五、使用抽象类实现多态
5.1 抽象类多态
using System;
namespace Week12Practice
{
// 抽象类:图形
abstract class Shape
{
public string Name { get; set; }
// 抽象方法:必须重写
public abstract double CalculateArea();
public abstract double CalculatePerimeter();
// 普通方法:可以重写
public virtual void Display()
{
Console.WriteLine($"图形: {Name}");
Console.WriteLine($"面积: {CalculateArea():F2}");
Console.WriteLine($"周长: {CalculatePerimeter():F2}");
}
}
// 具体类:圆形
class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Name = "圆形";
Radius = radius;
}
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
public override double CalculatePerimeter()
{
return 2 * Math.PI * Radius;
}
public override void Display()
{
base.Display();
Console.WriteLine($"半径: {Radius:F2}");
}
}
// 具体类:矩形
class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Name = "矩形";
Width = width;
Height = height;
}
public override double CalculateArea()
{
return Width * Height;
}
public override double CalculatePerimeter()
{
return 2 * (Width + Height);
}
public override void Display()
{
base.Display();
Console.WriteLine($"宽: {Width:F2}, 高: {Height:F2}");
}
}
// 具体类:三角形
class Triangle : Shape
{
public double Base { get; set; }
public double Height { get; set; }
public double SideA { get; set; }
public double SideB { get; set; }
public double SideC { get; set; }
public Triangle(double @base, double height, double sideA, double sideB, double sideC)
{
Name = "三角形";
Base = @base;
Height = height;
SideA = sideA;
SideB = sideB;
SideC = sideC;
}
public override double CalculateArea()
{
return 0.5 * Base * Height;
}
public override double CalculatePerimeter()
{
return SideA + SideB + SideC;
}
public override void Display()
{
base.Display();
Console.WriteLine($"底: {Base:F2}, 高: {Height:F2}");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 抽象类多态示例 =====\n");
Shape[] shapes = new Shape[]
{
new Circle(5),
new Rectangle(4, 6),
new Triangle(6, 4, 5, 5, 6)
};
double totalArea = 0;
foreach (Shape shape in shapes)
{
shape.Display(); // 多态:调用各自的 Display 方法
Console.WriteLine();
totalArea += shape.CalculateArea();
}
Console.WriteLine($"总面积: {totalArea:F2}");
}
}
}
输出:
===== 抽象类多态示例 =====
图形: 圆形
面积: 78.54
周长: 31.42
半径: 5.00
图形: 矩形
面积: 24.00
周长: 20.00
宽: 4.00, 高: 6.00
图形: 三角形
面积: 12.00
周长: 16.00
底: 6.00, 高: 4.00
总面积: 114.54
六、使用接口实现多态
6.1 接口多态
using System;
using System.Collections.Generic;
namespace Week12Practice
{
// 接口:可绘制
interface IDrawable
{
void Draw();
}
// 接口:可移动
interface IMovable
{
void Move(int x, int y);
}
// 实现 IDrawable 的类
class Circle : IDrawable
{
public double Radius { get; set; }
public Circle(double radius)
{
Radius = radius;
}
public void Draw()
{
Console.WriteLine($"绘制圆形,半径: {Radius}");
}
}
// 实现 IDrawable 的类
class Rectangle : IDrawable
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public void Draw()
{
Console.WriteLine($"绘制矩形,宽: {Width}, 高: {Height}");
}
}
// 同时实现 IDrawable 和 IMovable 的类
class Car : IDrawable, IMovable
{
public string Model { get; set; }
public Car(string model)
{
Model = model;
}
public void Draw()
{
Console.WriteLine($"绘制汽车,型号: {Model}");
}
public void Move(int x, int y)
{
Console.WriteLine($"汽车 {Model} 移动到 ({x}, {y})");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 接口多态示例 =====\n");
// IDrawable 多态
Console.WriteLine("--- 使用 IDrawable 接口 ---");
List<IDrawable> drawables = new List<IDrawable>
{
new Circle(5),
new Rectangle(4, 6),
new Car("宝马")
};
foreach (IDrawable drawable in drawables)
{
drawable.Draw(); // 多态:调用各自的 Draw 方法
}
// IMovable 多态
Console.WriteLine("\n--- 使用 IMovable 接口 ---");
List<IMovable> movables = new List<IMovable>
{
new Car("奔驰"),
new Car("奥迪")
};
foreach (IMovable movable in movables)
{
movable.Move(100, 200);
}
}
}
}
输出:
===== 接口多态示例 =====
--- 使用 IDrawable 接口 ---
绘制圆形,半径: 5
绘制矩形,宽: 4, 高: 6
绘制汽车,型号: 宝马
--- 使用 IMovable 接口 ---
汽车 奔驰 移动到 (100, 200)
汽车 奥迪 移动到 (100, 200)
七、实践示例:支付系统
using System;
using System.Collections.Generic;
namespace Week12Practice
{
// 抽象类:支付方式
abstract class PaymentMethod
{
public string Name { get; set; }
public decimal FeeRate { get; set; }
// 模板方法:定义支付流程
public bool ProcessPayment(decimal amount)
{
Console.WriteLine($"=== {Name} 支付处理 ===");
if (!Validate(amount))
{
Console.WriteLine("验证失败!");
return false;
}
decimal fee = CalculateFee(amount);
decimal total = amount + fee;
Console.WriteLine($"支付金额: {amount:C}");
Console.WriteLine($"手续费: {fee:C}");
Console.WriteLine($"总计: {total:C}");
if (ExecutePayment(total))
{
Console.WriteLine("✅ 支付成功!");
return true;
}
else
{
Console.WriteLine("❌ 支付失败!");
return false;
}
}
// 抽象方法:派生类必须实现
protected abstract bool Validate(decimal amount);
protected abstract bool ExecutePayment(decimal amount);
// 普通方法:默认实现
protected virtual decimal CalculateFee(decimal amount)
{
return amount * FeeRate;
}
}
// 具体类:信用卡支付
class CreditCardPayment : PaymentMethod
{
public string CardNumber { get; set; }
public CreditCardPayment(string cardNumber)
{
Name = "信用卡";
CardNumber = cardNumber;
FeeRate = 0.02m; // 2% 手续费
}
protected override bool Validate(decimal amount)
{
if (CardNumber.Length != 16)
{
Console.WriteLine("卡号格式错误!");
return false;
}
if (amount <= 0 || amount > 50000)
{
Console.WriteLine("金额必须在 0-50000 之间!");
return false;
}
return true;
}
protected override bool ExecutePayment(decimal amount)
{
Console.WriteLine("扣款中...");
// 模拟支付
return true;
}
}
// 具体类:支付宝支付
class AlipayPayment : PaymentMethod
{
public string AccountNumber { get; set; }
public AlipayPayment(string accountNumber)
{
Name = "支付宝";
AccountNumber = accountNumber;
FeeRate = 0.01m; // 1% 手续费
}
protected override bool Validate(decimal amount)
{
if (amount <= 0 || amount > 20000)
{
Console.WriteLine("金额必须在 0-20000 之间!");
return false;
}
return true;
}
protected override bool ExecutePayment(decimal amount)
{
Console.WriteLine("余额扣款中...");
// 模拟支付
return true;
}
}
// 具体类:微信支付
class WeChatPayment : PaymentMethod
{
public string OpenId { get; set; }
public WeChatPayment(string openId)
{
Name = "微信支付";
OpenId = openId;
FeeRate = 0.005m; // 0.5% 手续费
}
protected override bool Validate(decimal amount)
{
if (amount <= 0 || amount > 5000)
{
Console.WriteLine("金额必须在 0-5000 之间!");
return false;
}
return true;
}
protected override bool ExecutePayment(decimal amount)
{
Console.WriteLine("零钱扣款中...");
// 模拟支付
return true;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 支付系统多态示例 =====\n");
List<PaymentMethod> payments = new List<PaymentMethod>
{
new CreditCardPayment("1234567890123456"),
new AlipayPayment("zhangsan"),
new WeChatPayment("wx_zhangsan")
};
decimal[] amounts = { 100, 500, 299.99m };
for (int i = 0; i < payments.Count; i++)
{
payments[i].ProcessPayment(amounts[i]);
Console.WriteLine();
}
}
}
}
输出:
===== 支付系统多态示例 =====
=== 信用卡 支付处理 ===
支付金额: ¥100.00
手续费: ¥2.00
总计: ¥102.00
扣款中...
✅ 支付成功!
=== 支付宝 支付处理 ===
支付金额: ¥500.00
手续费: ¥5.00
总计: ¥505.00
余额扣款中...
✅ 支付成功!
=== 微信支付 支付处理 ===
支付金额: ¥299.99
手续费: ¥1.50
总计: ¥301.49
零钱扣款中...
✅ 支付成功!
八、多态的最佳实践
8.1 ✅ 推荐做法
- 使用多态处理不同类型
List<Animal> animals = { new Dog(), new Cat(), new Bird() };
foreach (var animal in animals)
{
animal.MakeSound(); // 多态调用
}
- 使用接口定义契约
interface ILogger
{
void Log(string message);
}
// 多个实现
class ConsoleLogger : ILogger { }
class FileLogger : ILogger { }
8.2 ❌ 不推荐做法
- 不要滥用多态
// ❌ 简单场景不需要多态
class Simple
{
public void Method() { }
}
- 不要忘记重写方法
// ❌ 忘记 override
class Child : Parent
{
public void Method() { } // 应该用 override
}
本章总结
- ✅ 理解了多态的概念和作用
- ✅ 学会了方法重载
- ✅ 掌握了方法重写(virtual/override)
- ✅ 学会了使用抽象类实现多态
- ✅ 学会了使用接口实现多态
- ✅ 实践了完整的支付系统