Skip to content

C# 多态

本章将详细介绍面向对象编程的第三个核心特性——多态,包括虚方法、抽象方法、接口多态等概念,帮助你编写更灵活和可扩展的代码。

多态的基本概念

什么是多态

csharp
// 多态(Polymorphism):同一个接口可以有多种不同的实现
// "一个接口,多种实现"

// 基类定义公共接口
public abstract class Shape
{
    protected string name;
    
    public Shape(string name)
    {
        this.name = name;
    }
    
    public string Name => name;
    
    // 抽象方法 - 强制派生类实现
    public abstract double CalculateArea();
    public abstract double CalculatePerimeter();
    
    // 虚方法 - 可以被重写
    public virtual void Display()
    {
        Console.WriteLine($"形状: {name}");
        Console.WriteLine($"面积: {CalculateArea():F2}");
        Console.WriteLine($"周长: {CalculatePerimeter():F2}");
    }
}

// 不同的实现
public class Circle : Shape
{
    private double radius;
    
    public Circle(double radius) : base("圆形")
    {
        this.radius = radius;
    }
    
    public double 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}");
    }
}

public class Rectangle : Shape
{
    private double width, height;
    
    public Rectangle(double width, double height) : base("矩形")
    {
        this.width = width;
        this.height = height;
    }
    
    public double Width => width;
    public double 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}, 高度: {height}");
    }
}

public class Triangle : Shape
{
    private double sideA, sideB, sideC;
    
    public Triangle(double sideA, double sideB, double sideC) : base("三角形")
    {
        this.sideA = sideA;
        this.sideB = sideB;
        this.sideC = sideC;
    }
    
    public override double CalculateArea()
    {
        // 使用海伦公式计算面积
        double s = (sideA + sideB + sideC) / 2;
        return Math.Sqrt(s * (s - sideA) * (s - sideB) * (s - sideC));
    }
    
    public override double CalculatePerimeter()
    {
        return sideA + sideB + sideC;
    }
    
    public override void Display()
    {
        base.Display();
        Console.WriteLine($"边长: {sideA}, {sideB}, {sideC}");
    }
}

static void BasicPolymorphismDemo()
{
    Console.WriteLine("=== 基本多态演示 ===");
    
    // 多态性:基类引用指向不同的派生类对象
    Shape[] shapes = {
        new Circle(5.0),
        new Rectangle(4.0, 6.0),
        new Triangle(3.0, 4.0, 5.0)
    };
    
    // 统一的接口,不同的实现
    foreach (Shape shape in shapes)
    {
        shape.Display();  // 调用相应派生类的实现
        Console.WriteLine();
    }
    
    // 计算总面积
    double totalArea = 0;
    foreach (Shape shape in shapes)
    {
        totalArea += shape.CalculateArea();
    }
    
    Console.WriteLine($"所有形状的总面积: {totalArea:F2}");
}

多态的类型

csharp
// 1. 编译时多态(静态多态)- 方法重载
public class Calculator
{
    // 方法重载 - 编译时确定调用哪个方法
    public int Add(int a, int b)
    {
        Console.WriteLine("调用 int Add(int, int)");
        return a + b;
    }
    
    public double Add(double a, double b)
    {
        Console.WriteLine("调用 double Add(double, double)");
        return a + b;
    }
    
    public string Add(string a, string b)
    {
        Console.WriteLine("调用 string Add(string, string)");
        return a + b;
    }
    
    public int Add(int a, int b, int c)
    {
        Console.WriteLine("调用 int Add(int, int, int)");
        return a + b + c;
    }
}

// 2. 运行时多态(动态多态)- 虚方法重写
public abstract class Animal
{
    protected string name;
    
    public Animal(string name)
    {
        this.name = name;
    }
    
    public string Name => name;
    
    // 虚方法 - 运行时确定调用哪个实现
    public virtual void MakeSound()
    {
        Console.WriteLine($"{name} 发出声音");
    }
    
    public virtual void Move()
    {
        Console.WriteLine($"{name} 在移动");
    }
    
    // 抽象方法 - 必须重写
    public abstract void Eat();
}

public class Dog : Animal
{
    public Dog(string name) : base(name) { }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{name} 汪汪叫");
    }
    
    public override void Move()
    {
        Console.WriteLine($"{name} 在奔跑");
    }
    
    public override void Eat()
    {
        Console.WriteLine($"{name} 在吃狗粮");
    }
    
    // 新增方法
    public void Fetch()
    {
        Console.WriteLine($"{name} 在捡球");
    }
}

public class Cat : Animal
{
    public Cat(string name) : base(name) { }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{name} 喵喵叫");
    }
    
    public override void Move()
    {
        Console.WriteLine($"{name} 在悄悄走动");
    }
    
    public override void Eat()
    {
        Console.WriteLine($"{name} 在吃猫粮");
    }
    
    public void Climb()
    {
        Console.WriteLine($"{name} 在爬树");
    }
}

public class Bird : Animal
{
    public Bird(string name) : base(name) { }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{name} 在唱歌");
    }
    
    public override void Move()
    {
        Console.WriteLine($"{name} 在飞翔");
    }
    
    public override void Eat()
    {
        Console.WriteLine($"{name} 在吃虫子");
    }
    
    public void Fly()
    {
        Console.WriteLine($"{name} 在高空飞行");
    }
}

static void PolymorphismTypesDemo()
{
    Console.WriteLine("=== 多态类型演示 ===");
    
    // 编译时多态
    Console.WriteLine("1. 编译时多态(方法重载):");
    Calculator calc = new Calculator();
    calc.Add(1, 2);
    calc.Add(1.5, 2.5);
    calc.Add("Hello", "World");
    calc.Add(1, 2, 3);
    
    // 运行时多态
    Console.WriteLine("\n2. 运行时多态(虚方法重写):");
    Animal[] animals = {
        new Dog("旺财"),
        new Cat("咪咪"),
        new Bird("小鸟")
    };
    
    foreach (Animal animal in animals)
    {
        Console.WriteLine($"\n--- {animal.Name} ---");
        animal.MakeSound();  // 多态调用
        animal.Move();       // 多态调用
        animal.Eat();        // 多态调用
    }
}

虚方法和抽象方法

虚方法的深入应用

csharp
public class Vehicle
{
    protected string brand;
    protected int year;
    protected decimal price;
    
    public Vehicle(string brand, int year, decimal price)
    {
        this.brand = brand;
        this.year = year;
        this.price = price;
    }
    
    public string Brand => brand;
    public int Year => year;
    public decimal Price => price;
    
    // 虚方法 - 提供默认实现,可以被重写
    public virtual void Start()
    {
        Console.WriteLine($"{brand} 正在启动...");
    }
    
    public virtual void Stop()
    {
        Console.WriteLine($"{brand} 已停止");
    }
    
    public virtual decimal CalculateInsurance()
    {
        return price * 0.05m;  // 默认保险费率 5%
    }
    
    public virtual string GetVehicleInfo()
    {
        return $"{brand} {year}年款,价格: {price:C}";
    }
    
    // 模板方法模式 - 定义算法骨架
    public void PerformMaintenance()
    {
        Console.WriteLine($"开始维护 {brand}:");
        CheckEngine();      // 虚方法
        CheckTires();       // 虚方法
        CheckFluids();      // 虚方法
        PerformSpecificMaintenance();  // 抽象方法
        Console.WriteLine("维护完成\n");
    }
    
    protected virtual void CheckEngine()
    {
        Console.WriteLine("- 检查发动机");
    }
    
    protected virtual void CheckTires()
    {
        Console.WriteLine("- 检查轮胎");
    }
    
    protected virtual void CheckFluids()
    {
        Console.WriteLine("- 检查液体");
    }
    
    protected virtual void PerformSpecificMaintenance()
    {
        Console.WriteLine("- 执行通用维护");
    }
}

public class Car : Vehicle
{
    private int doors;
    private string fuelType;
    
    public Car(string brand, int year, decimal price, int doors, string fuelType) 
        : base(brand, year, price)
    {
        this.doors = doors;
        this.fuelType = fuelType;
    }
    
    public int Doors => doors;
    public string FuelType => fuelType;
    
    public override void Start()
    {
        Console.WriteLine($"{brand} 汽车启动,{fuelType}发动机运转");
    }
    
    public override decimal CalculateInsurance()
    {
        decimal baseInsurance = base.CalculateInsurance();
        // 汽车保险费率根据门数调整
        decimal doorFactor = doors == 2 ? 1.2m : 1.0m;
        return baseInsurance * doorFactor;
    }
    
    public override string GetVehicleInfo()
    {
        return base.GetVehicleInfo() + $", {doors}门 {fuelType}汽车";
    }
    
    protected override void PerformSpecificMaintenance()
    {
        Console.WriteLine("- 检查空调系统");
        Console.WriteLine("- 检查音响系统");
        Console.WriteLine("- 清洁内饰");
    }
}

public class Motorcycle : Vehicle
{
    private int engineSize;
    
    public Motorcycle(string brand, int year, decimal price, int engineSize) 
        : base(brand, year, price)
    {
        this.engineSize = engineSize;
    }
    
    public int EngineSize => engineSize;
    
    public override void Start()
    {
        Console.WriteLine($"{brand} 摩托车启动,{engineSize}cc发动机轰鸣");
    }
    
    public override decimal CalculateInsurance()
    {
        decimal baseInsurance = base.CalculateInsurance();
        // 摩托车保险费率更高
        return baseInsurance * 1.5m;
    }
    
    public override string GetVehicleInfo()
    {
        return base.GetVehicleInfo() + $", {engineSize}cc摩托车";
    }
    
    protected override void CheckTires()
    {
        Console.WriteLine("- 检查摩托车轮胎气压和磨损");
    }
    
    protected override void PerformSpecificMaintenance()
    {
        Console.WriteLine("- 检查链条润滑");
        Console.WriteLine("- 检查刹车片");
        Console.WriteLine("- 调整后视镜");
    }
}

public class Truck : Vehicle
{
    private double loadCapacity;
    
    public Truck(string brand, int year, decimal price, double loadCapacity) 
        : base(brand, year, price)
    {
        this.loadCapacity = loadCapacity;
    }
    
    public double LoadCapacity => loadCapacity;
    
    public override void Start()
    {
        Console.WriteLine($"{brand} 卡车启动,载重量 {loadCapacity}吨");
    }
    
    public override decimal CalculateInsurance()
    {
        decimal baseInsurance = base.CalculateInsurance();
        // 卡车保险费率根据载重量调整
        decimal loadFactor = (decimal)(1.0 + loadCapacity * 0.1);
        return baseInsurance * loadFactor;
    }
    
    public override string GetVehicleInfo()
    {
        return base.GetVehicleInfo() + $", 载重 {loadCapacity}吨卡车";
    }
    
    protected override void CheckEngine()
    {
        Console.WriteLine("- 检查大型柴油发动机");
    }
    
    protected override void PerformSpecificMaintenance()
    {
        Console.WriteLine("- 检查货厢");
        Console.WriteLine("- 检查液压系统");
        Console.WriteLine("- 润滑传动系统");
    }
}

static void VirtualMethodDemo()
{
    Console.WriteLine("=== 虚方法演示 ===");
    
    Vehicle[] vehicles = {
        new Car("丰田", 2023, 200000m, 4, "汽油"),
        new Motorcycle("哈雷", 2022, 150000m, 1200),
        new Truck("沃尔沃", 2021, 500000m, 10.0)
    };
    
    foreach (Vehicle vehicle in vehicles)
    {
        Console.WriteLine(vehicle.GetVehicleInfo());
        vehicle.Start();
        Console.WriteLine($"保险费: {vehicle.CalculateInsurance():C}");
        vehicle.PerformMaintenance();
    }
}

抽象方法的应用

csharp
// 抽象基类定义公共接口
public abstract class DatabaseConnection
{
    protected string connectionString;
    protected bool isConnected;
    
    public DatabaseConnection(string connectionString)
    {
        this.connectionString = connectionString;
        this.isConnected = false;
    }
    
    public string ConnectionString => connectionString;
    public bool IsConnected => isConnected;
    
    // 抽象方法 - 强制派生类实现
    public abstract void Connect();
    public abstract void Disconnect();
    public abstract void ExecuteQuery(string query);
    public abstract void BeginTransaction();
    public abstract void CommitTransaction();
    public abstract void RollbackTransaction();
    
    // 虚方法 - 提供默认实现,可以重写
    public virtual void TestConnection()
    {
        Console.WriteLine("测试数据库连接...");
        Connect();
        if (isConnected)
        {
            Console.WriteLine("连接测试成功");
            Disconnect();
        }
        else
        {
            Console.WriteLine("连接测试失败");
        }
    }
    
    // 模板方法 - 定义操作流程
    public void ExecuteWithTransaction(string[] queries)
    {
        try
        {
            Connect();
            BeginTransaction();
            
            foreach (string query in queries)
            {
                ExecuteQuery(query);
            }
            
            CommitTransaction();
            Console.WriteLine("事务执行成功");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"事务执行失败: {ex.Message}");
            RollbackTransaction();
        }
        finally
        {
            Disconnect();
        }
    }
}

public class SqlServerConnection : DatabaseConnection
{
    public SqlServerConnection(string connectionString) : base(connectionString) { }
    
    public override void Connect()
    {
        Console.WriteLine($"连接到 SQL Server: {connectionString}");
        isConnected = true;
    }
    
    public override void Disconnect()
    {
        Console.WriteLine("断开 SQL Server 连接");
        isConnected = false;
    }
    
    public override void ExecuteQuery(string query)
    {
        if (!isConnected)
            throw new InvalidOperationException("未连接到数据库");
        Console.WriteLine($"SQL Server 执行查询: {query}");
    }
    
    public override void BeginTransaction()
    {
        Console.WriteLine("SQL Server 开始事务");
    }
    
    public override void CommitTransaction()
    {
        Console.WriteLine("SQL Server 提交事务");
    }
    
    public override void RollbackTransaction()
    {
        Console.WriteLine("SQL Server 回滚事务");
    }
    
    public override void TestConnection()
    {
        Console.WriteLine("SQL Server 专用连接测试");
        base.TestConnection();
    }
}

public class MySqlConnection : DatabaseConnection
{
    public MySqlConnection(string connectionString) : base(connectionString) { }
    
    public override void Connect()
    {
        Console.WriteLine($"连接到 MySQL: {connectionString}");
        isConnected = true;
    }
    
    public override void Disconnect()
    {
        Console.WriteLine("断开 MySQL 连接");
        isConnected = false;
    }
    
    public override void ExecuteQuery(string query)
    {
        if (!isConnected)
            throw new InvalidOperationException("未连接到数据库");
        Console.WriteLine($"MySQL 执行查询: {query}");
    }
    
    public override void BeginTransaction()
    {
        Console.WriteLine("MySQL 开始事务");
    }
    
    public override void CommitTransaction()
    {
        Console.WriteLine("MySQL 提交事务");
    }
    
    public override void RollbackTransaction()
    {
        Console.WriteLine("MySQL 回滚事务");
    }
}

public class OracleConnection : DatabaseConnection
{
    public OracleConnection(string connectionString) : base(connectionString) { }
    
    public override void Connect()
    {
        Console.WriteLine($"连接到 Oracle: {connectionString}");
        isConnected = true;
    }
    
    public override void Disconnect()
    {
        Console.WriteLine("断开 Oracle 连接");
        isConnected = false;
    }
    
    public override void ExecuteQuery(string query)
    {
        if (!isConnected)
            throw new InvalidOperationException("未连接到数据库");
        Console.WriteLine($"Oracle 执行查询: {query}");
    }
    
    public override void BeginTransaction()
    {
        Console.WriteLine("Oracle 开始事务");
    }
    
    public override void CommitTransaction()
    {
        Console.WriteLine("Oracle 提交事务");
    }
    
    public override void RollbackTransaction()
    {
        Console.WriteLine("Oracle 回滚事务");
    }
}

// 数据库管理器 - 使用多态
public class DatabaseManager
{
    private List<DatabaseConnection> connections;
    
    public DatabaseManager()
    {
        connections = new List<DatabaseConnection>();
    }
    
    public void AddConnection(DatabaseConnection connection)
    {
        connections.Add(connection);
    }
    
    public void TestAllConnections()
    {
        Console.WriteLine("测试所有数据库连接:");
        foreach (var connection in connections)
        {
            connection.TestConnection();
            Console.WriteLine();
        }
    }
    
    public void ExecuteQueryOnAll(string query)
    {
        Console.WriteLine($"在所有数据库上执行查询: {query}");
        foreach (var connection in connections)
        {
            try
            {
                connection.Connect();
                connection.ExecuteQuery(query);
                connection.Disconnect();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"执行失败: {ex.Message}");
            }
            Console.WriteLine();
        }
    }
}

static void AbstractMethodDemo()
{
    Console.WriteLine("=== 抽象方法演示 ===");
    
    DatabaseManager manager = new DatabaseManager();
    
    // 添加不同类型的数据库连接
    manager.AddConnection(new SqlServerConnection("Server=localhost;Database=TestDB"));
    manager.AddConnection(new MySqlConnection("Server=localhost;Database=testdb;Uid=root"));
    manager.AddConnection(new OracleConnection("Data Source=localhost:1521/XE"));
    
    // 多态调用
    manager.TestAllConnections();
    manager.ExecuteQueryOnAll("SELECT * FROM Users");
    
    // 事务演示
    Console.WriteLine("=== 事务演示 ===");
    var sqlConnection = new SqlServerConnection("Server=localhost;Database=TestDB");
    string[] queries = {
        "INSERT INTO Users (Name) VALUES ('Alice')",
        "INSERT INTO Users (Name) VALUES ('Bob')",
        "UPDATE Users SET Active = 1"
    };
    
    sqlConnection.ExecuteWithTransaction(queries);
}

接口多态

接口的定义和实现

csharp
// 接口定义契约
public interface IDrawable
{
    void Draw();
    void Move(int x, int y);
    bool IsVisible { get; set; }
}

public interface IResizable
{
    void Resize(double factor);
    double GetArea();
}

public interface IColorable
{
    ConsoleColor Color { get; set; }
    void ChangeColor(ConsoleColor newColor);
}

// 实现多个接口
public class DrawableRectangle : IDrawable, IResizable, IColorable
{
    private int x, y;
    private double width, height;
    private ConsoleColor color;
    private bool isVisible;
    
    public DrawableRectangle(int x, int y, double width, double height, ConsoleColor color = ConsoleColor.White)
    {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.color = color;
        this.isVisible = true;
    }
    
    // IDrawable 实现
    public void Draw()
    {
        if (isVisible)
        {
            Console.ForegroundColor = color;
            Console.WriteLine($"绘制矩形在 ({x}, {y}),大小: {width} x {height}");
            Console.ResetColor();
        }
    }
    
    public void Move(int newX, int newY)
    {
        x = newX;
        y = newY;
        Console.WriteLine($"矩形移动到 ({x}, {y})");
    }
    
    public bool IsVisible
    {
        get => isVisible;
        set
        {
            isVisible = value;
            Console.WriteLine($"矩形可见性: {(isVisible ? "显示" : "隐藏")}");
        }
    }
    
    // IResizable 实现
    public void Resize(double factor)
    {
        width *= factor;
        height *= factor;
        Console.WriteLine($"矩形缩放 {factor}倍,新大小: {width:F2} x {height:F2}");
    }
    
    public double GetArea()
    {
        return width * height;
    }
    
    // IColorable 实现
    public ConsoleColor Color
    {
        get => color;
        set
        {
            color = value;
            Console.WriteLine($"矩形颜色改为: {color}");
        }
    }
    
    public void ChangeColor(ConsoleColor newColor)
    {
        Color = newColor;
    }
}

public class DrawableCircle : IDrawable, IResizable, IColorable
{
    private int x, y;
    private double radius;
    private ConsoleColor color;
    private bool isVisible;
    
    public DrawableCircle(int x, int y, double radius, ConsoleColor color = ConsoleColor.White)
    {
        this.x = x;
        this.y = y;
        this.radius = radius;
        this.color = color;
        this.isVisible = true;
    }
    
    public void Draw()
    {
        if (isVisible)
        {
            Console.ForegroundColor = color;
            Console.WriteLine($"绘制圆形在 ({x}, {y}),半径: {radius}");
            Console.ResetColor();
        }
    }
    
    public void Move(int newX, int newY)
    {
        x = newX;
        y = newY;
        Console.WriteLine($"圆形移动到 ({x}, {y})");
    }
    
    public bool IsVisible
    {
        get => isVisible;
        set
        {
            isVisible = value;
            Console.WriteLine($"圆形可见性: {(isVisible ? "显示" : "隐藏")}");
        }
    }
    
    public void Resize(double factor)
    {
        radius *= factor;
        Console.WriteLine($"圆形缩放 {factor}倍,新半径: {radius:F2}");
    }
    
    public double GetArea()
    {
        return Math.PI * radius * radius;
    }
    
    public ConsoleColor Color
    {
        get => color;
        set
        {
            color = value;
            Console.WriteLine($"圆形颜色改为: {color}");
        }
    }
    
    public void ChangeColor(ConsoleColor newColor)
    {
        Color = newColor;
    }
}

// 图形管理器 - 使用接口多态
public class GraphicsManager
{
    private List<IDrawable> drawables;
    private List<IResizable> resizables;
    private List<IColorable> colorables;
    
    public GraphicsManager()
    {
        drawables = new List<IDrawable>();
        resizables = new List<IResizable>();
        colorables = new List<IColorable>();
    }
    
    public void AddShape(object shape)
    {
        if (shape is IDrawable drawable)
            drawables.Add(drawable);
        
        if (shape is IResizable resizable)
            resizables.Add(resizable);
        
        if (shape is IColorable colorable)
            colorables.Add(colorable);
    }
    
    public void DrawAll()
    {
        Console.WriteLine("绘制所有图形:");
        foreach (var drawable in drawables)
        {
            drawable.Draw();
        }
    }
    
    public void MoveAll(int deltaX, int deltaY)
    {
        Console.WriteLine($"移动所有图形 ({deltaX}, {deltaY}):");
        foreach (var drawable in drawables)
        {
            // 这里需要获取当前位置,简化处理
            drawable.Move(deltaX, deltaY);
        }
    }
    
    public void ResizeAll(double factor)
    {
        Console.WriteLine($"缩放所有可调整大小的图形 {factor}倍:");
        foreach (var resizable in resizables)
        {
            resizable.Resize(factor);
        }
    }
    
    public void ChangeAllColors(ConsoleColor newColor)
    {
        Console.WriteLine($"将所有图形颜色改为 {newColor}:");
        foreach (var colorable in colorables)
        {
            colorable.ChangeColor(newColor);
        }
    }
    
    public void ShowStatistics()
    {
        Console.WriteLine("图形统计:");
        Console.WriteLine($"可绘制图形: {drawables.Count}");
        Console.WriteLine($"可调整大小图形: {resizables.Count}");
        Console.WriteLine($"可着色图形: {colorables.Count}");
        
        double totalArea = 0;
        foreach (var resizable in resizables)
        {
            totalArea += resizable.GetArea();
        }
        Console.WriteLine($"总面积: {totalArea:F2}");
    }
}

static void InterfacePolymorphismDemo()
{
    Console.WriteLine("=== 接口多态演示 ===");
    
    GraphicsManager manager = new GraphicsManager();
    
    // 添加不同类型的图形
    manager.AddShape(new DrawableRectangle(10, 10, 5, 3, ConsoleColor.Red));
    manager.AddShape(new DrawableCircle(20, 20, 4, ConsoleColor.Blue));
    manager.AddShape(new DrawableRectangle(30, 30, 6, 4, ConsoleColor.Green));
    
    // 使用接口多态
    manager.DrawAll();
    Console.WriteLine();
    
    manager.ShowStatistics();
    Console.WriteLine();
    
    manager.ResizeAll(1.5);
    Console.WriteLine();
    
    manager.ChangeAllColors(ConsoleColor.Yellow);
    Console.WriteLine();
    
    manager.DrawAll();
}

实践示例

示例 1:支付系统

csharp
using System;
using System.Collections.Generic;

// 支付接口
public interface IPaymentProcessor
{
    bool ProcessPayment(decimal amount, string currency = "CNY");
    bool RefundPayment(string transactionId, decimal amount);
    string GetPaymentMethod();
    decimal GetTransactionFee(decimal amount);
}

// 抽象支付基类
public abstract class PaymentProcessorBase : IPaymentProcessor
{
    protected string merchantId;
    protected bool isEnabled;
    
    public PaymentProcessorBase(string merchantId)
    {
        this.merchantId = merchantId;
        this.isEnabled = true;
    }
    
    public string MerchantId => merchantId;
    public bool IsEnabled => isEnabled;
    
    // 抽象方法 - 子类必须实现
    public abstract bool ProcessPayment(decimal amount, string currency = "CNY");
    public abstract bool RefundPayment(string transactionId, decimal amount);
    public abstract string GetPaymentMethod();
    public abstract decimal GetTransactionFee(decimal amount);
    
    // 虚方法 - 可以被重写
    public virtual bool ValidateAmount(decimal amount)
    {
        return amount > 0 && amount <= GetMaxAmount();
    }
    
    public virtual decimal GetMaxAmount()
    {
        return 100000m;  // 默认最大金额
    }
    
    // 模板方法
    public bool ExecutePayment(decimal amount, string currency = "CNY")
    {
        if (!isEnabled)
        {
            Console.WriteLine($"{GetPaymentMethod()} 支付已禁用");
            return false;
        }
        
        if (!ValidateAmount(amount))
        {
            Console.WriteLine($"金额验证失败: {amount:C}");
            return false;
        }
        
        decimal fee = GetTransactionFee(amount);
        Console.WriteLine($"使用 {GetPaymentMethod()} 支付 {amount:C},手续费: {fee:C}");
        
        return ProcessPayment(amount, currency);
    }
}

// 支付宝支付
public class AlipayProcessor : PaymentProcessorBase
{
    private string appId;
    
    public AlipayProcessor(string merchantId, string appId) : base(merchantId)
    {
        this.appId = appId;
    }
    
    public override bool ProcessPayment(decimal amount, string currency = "CNY")
    {
        Console.WriteLine($"支付宝处理支付: {amount:C} {currency}");
        // 模拟支付处理
        bool success = new Random().Next(1, 11) > 1; // 90% 成功率
        Console.WriteLine($"支付宝支付{(success ? "成功" : "失败")}");
        return success;
    }
    
    public override bool RefundPayment(string transactionId, decimal amount)
    {
        Console.WriteLine($"支付宝退款: 交易ID {transactionId},金额 {amount:C}");
        return true;
    }
    
    public override string GetPaymentMethod()
    {
        return "支付宝";
    }
    
    public override decimal GetTransactionFee(decimal amount)
    {
        return amount * 0.006m;  // 0.6% 手续费
    }
    
    public override decimal GetMaxAmount()
    {
        return 200000m;  // 支付宝单笔限额更高
    }
}

// 微信支付
public class WeChatPayProcessor : PaymentProcessorBase
{
    private string appSecret;
    
    public WeChatPayProcessor(string merchantId, string appSecret) : base(merchantId)
    {
        this.appSecret = appSecret;
    }
    
    public override bool ProcessPayment(decimal amount, string currency = "CNY")
    {
        Console.WriteLine($"微信支付处理支付: {amount:C} {currency}");
        bool success = new Random().Next(1, 11) > 2; // 80% 成功率
        Console.WriteLine($"微信支付{(success ? "成功" : "失败")}");
        return success;
    }
    
    public override bool RefundPayment(string transactionId, decimal amount)
    {
        Console.WriteLine($"微信支付退款: 交易ID {transactionId},金额 {amount:C}");
        return true;
    }
    
    public override string GetPaymentMethod()
    {
        return "微信支付";
    }
    
    public override decimal GetTransactionFee(decimal amount)
    {
        return amount * 0.006m;  // 0.6% 手续费
    }
}

// 银行卡支付
public class BankCardProcessor : PaymentProcessorBase
{
    private string bankCode;
    
    public BankCardProcessor(string merchantId, string bankCode) : base(merchantId)
    {
        this.bankCode = bankCode;
    }
    
    public override bool ProcessPayment(decimal amount, string currency = "CNY")
    {
        Console.WriteLine($"银行卡支付处理: {amount:C} {currency},银行代码: {bankCode}");
        bool success = new Random().Next(1, 11) > 3; // 70% 成功率
        Console.WriteLine($"银行卡支付{(success ? "成功" : "失败")}");
        return success;
    }
    
    public override bool RefundPayment(string transactionId, decimal amount)
    {
        Console.WriteLine($"银行卡退款: 交易ID {transactionId},金额 {amount:C}");
        return true;
    }
    
    public override string GetPaymentMethod()
    {
        return $"银行卡({bankCode})";
    }
    
    public override decimal GetTransactionFee(decimal amount)
    {
        return amount * 0.008m;  // 0.8% 手续费
    }
    
    public override bool ValidateAmount(decimal amount)
    {
        // 银行卡支付额外验证
        return base.ValidateAmount(amount) && amount >= 1m;  // 最小1元
    }
}

// 支付管理器
public class PaymentManager
{
    private List<IPaymentProcessor> processors;
    private IPaymentProcessor defaultProcessor;
    
    public PaymentManager()
    {
        processors = new List<IPaymentProcessor>();
    }
    
    public void AddProcessor(IPaymentProcessor processor)
    {
        processors.Add(processor);
        if (defaultProcessor == null)
            defaultProcessor = processor;
    }
    
    public void SetDefaultProcessor(IPaymentProcessor processor)
    {
        defaultProcessor = processor;
    }
    
    public bool ProcessPayment(decimal amount, string preferredMethod = null)
    {
        IPaymentProcessor processor = null;
        
        // 选择支付方式
        if (!string.IsNullOrEmpty(preferredMethod))
        {
            processor = processors.Find(p => p.GetPaymentMethod().Contains(preferredMethod));
        }
        
        processor ??= defaultProcessor;
        
        if (processor == null)
        {
            Console.WriteLine("没有可用的支付处理器");
            return false;
        }
        
        // 使用多态调用
        if (processor is PaymentProcessorBase baseProcessor)
        {
            return baseProcessor.ExecutePayment(amount);
        }
        else
        {
            return processor.ProcessPayment(amount);
        }
    }
    
    public void ShowAvailablePaymentMethods()
    {
        Console.WriteLine("可用支付方式:");
        foreach (var processor in processors)
        {
            decimal sampleFee = processor.GetTransactionFee(100m);
            Console.WriteLine($"- {processor.GetPaymentMethod()}: 手续费率 {sampleFee:P2}");
        }
    }
    
    public void ProcessMultiplePayments(decimal[] amounts)
    {
        Console.WriteLine("批量支付处理:");
        foreach (decimal amount in amounts)
        {
            Console.WriteLine($"\n处理支付: {amount:C}");
            
            // 根据金额选择最优支付方式
            IPaymentProcessor bestProcessor = GetBestProcessor(amount);
            if (bestProcessor is PaymentProcessorBase baseProcessor)
            {
                baseProcessor.ExecutePayment(amount);
            }
        }
    }
    
    private IPaymentProcessor GetBestProcessor(decimal amount)
    {
        // 选择手续费最低的支付方式
        IPaymentProcessor best = null;
        decimal lowestFee = decimal.MaxValue;
        
        foreach (var processor in processors)
        {
            decimal fee = processor.GetTransactionFee(amount);
            if (fee < lowestFee)
            {
                lowestFee = fee;
                best = processor;
            }
        }
        
        return best ?? defaultProcessor;
    }
}

static void PaymentSystemDemo()
{
    Console.WriteLine("=== 支付系统演示 ===");
    
    PaymentManager manager = new PaymentManager();
    
    // 添加不同的支付处理器
    manager.AddProcessor(new AlipayProcessor("MERCHANT001", "APP001"));
    manager.AddProcessor(new WeChatPayProcessor("MERCHANT001", "SECRET001"));
    manager.AddProcessor(new BankCardProcessor("MERCHANT001", "ICBC"));
    
    // 显示可用支付方式
    manager.ShowAvailablePaymentMethods();
    
    Console.WriteLine("\n=== 单笔支付测试 ===");
    manager.ProcessPayment(1000m, "支付宝");
    manager.ProcessPayment(500m, "微信");
    manager.ProcessPayment(2000m, "银行卡");
    
    Console.WriteLine("\n=== 批量支付测试 ===");
    decimal[] amounts = { 100m, 500m, 1500m, 3000m };
    manager.ProcessMultiplePayments(amounts);
}

示例 2:文档处理系统

csharp
using System;
using System.Collections.Generic;
using System.IO;

// 文档接口
public interface IDocument
{
    string FileName { get; }
    long FileSize { get; }
    DateTime CreatedDate { get; }
    void Open();
    void Save();
    void Close();
    string GetContent();
}

public interface IEditableDocument : IDocument
{
    void SetContent(string content);
    void AppendContent(string content);
    bool IsModified { get; }
}

public interface IPrintableDocument : IDocument
{
    void Print();
    void PrintPreview();
    int GetPageCount();
}

public interface IExportableDocument : IDocument
{
    void ExportToPdf(string filePath);
    void ExportToHtml(string filePath);
}

// 抽象文档基类
public abstract class DocumentBase : IDocument
{
    protected string fileName;
    protected long fileSize;
    protected DateTime createdDate;
    protected bool isOpen;
    protected string content;
    
    public DocumentBase(string fileName)
    {
        this.fileName = fileName;
        this.fileSize = 0;
        this.createdDate = DateTime.Now;
        this.isOpen = false;
        this.content = "";
    }
    
    public string FileName => fileName;
    public long FileSize => fileSize;
    public DateTime CreatedDate => createdDate;
    public bool IsOpen => isOpen;
    
    public virtual void Open()
    {
        if (!isOpen)
        {
            Console.WriteLine($"打开文档: {fileName}");
            LoadContent();
            isOpen = true;
        }
    }
    
    public virtual void Close()
    {
        if (isOpen)
        {
            Console.WriteLine($"关闭文档: {fileName}");
            isOpen = false;
        }
    }
    
    public abstract void Save();
    public abstract string GetContent();
    protected abstract void LoadContent();
}

// 文本文档
public class TextDocument : DocumentBase, IEditableDocument, IPrintableDocument, IExportableDocument
{
    private bool isModified;
    
    public TextDocument(string fileName) : base(fileName)
    {
        this.isModified = false;
    }
    
    public bool IsModified => isModified;
    
    protected override void LoadContent()
    {
        // 模拟从文件加载内容
        content = $"这是文本文档 {fileName} 的内容。\n创建时间: {createdDate}";
        fileSize = content.Length;
    }
    
    public override void Save()
    {
        if (isModified)
        {
            Console.WriteLine($"保存文本文档: {fileName}");
            fileSize = content.Length;
            isModified = false;
        }
        else
        {
            Console.WriteLine($"文档 {fileName} 无需保存");
        }
    }
    
    public override string GetContent()
    {
        return content;
    }
    
    public void SetContent(string newContent)
    {
        if (content != newContent)
        {
            content = newContent;
            isModified = true;
            Console.WriteLine($"文档 {fileName} 内容已修改");
        }
    }
    
    public void AppendContent(string additionalContent)
    {
        content += additionalContent;
        isModified = true;
        Console.WriteLine($"向文档 {fileName} 追加内容");
    }
    
    public void Print()
    {
        Console.WriteLine($"打印文本文档: {fileName}");
        Console.WriteLine("--- 打印内容 ---");
        Console.WriteLine(content);
        Console.WriteLine("--- 打印结束 ---");
    }
    
    public void PrintPreview()
    {
        Console.WriteLine($"文本文档 {fileName} 打印预览:");
        Console.WriteLine($"页数: {GetPageCount()}");
        Console.WriteLine($"字符数: {content.Length}");
    }
    
    public int GetPageCount()
    {
        return Math.Max(1, content.Length / 500);  // 假设每页500字符
    }
    
    public void ExportToPdf(string filePath)
    {
        Console.WriteLine($"将文本文档 {fileName} 导出为PDF: {filePath}");
    }
    
    public void ExportToHtml(string filePath)
    {
        Console.WriteLine($"将文本文档 {fileName} 导出为HTML: {filePath}");
    }
}

// 图片文档
public class ImageDocument : DocumentBase, IPrintableDocument, IExportableDocument
{
    private int width, height;
    private string format;
    
    public ImageDocument(string fileName, int width, int height, string format) : base(fileName)
    {
        this.width = width;
        this.height = height;
        this.format = format;
    }
    
    public int Width => width;
    public int Height => height;
    public string Format => format;
    
    protected override void LoadContent()
    {
        content = $"图片文档: {fileName} ({width}x{height}, {format})";
        fileSize = width * height * 3;  // 假设RGB格式
    }
    
    public override void Save()
    {
        Console.WriteLine($"保存图片文档: {fileName}");
    }
    
    public override string GetContent()
    {
        return $"图片信息: {width}x{height} {format}格式";
    }
    
    public void Print()
    {
        Console.WriteLine($"打印图片文档: {fileName}");
        Console.WriteLine($"图片尺寸: {width}x{height}");
        Console.WriteLine($"格式: {format}");
    }
    
    public void PrintPreview()
    {
        Console.WriteLine($"图片文档 {fileName} 打印预览:");
        Console.WriteLine($"尺寸: {width}x{height}");
        Console.WriteLine($"格式: {format}");
        Console.WriteLine($"文件大小: {fileSize} 字节");
    }
    
    public int GetPageCount()
    {
        return 1;  // 图片通常只有一页
    }
    
    public void ExportToPdf(string filePath)
    {
        Console.WriteLine($"将图片文档 {fileName} 导出为PDF: {filePath}");
    }
    
    public void ExportToHtml(string filePath)
    {
        Console.WriteLine($"将图片文档 {fileName} 嵌入HTML: {filePath}");
    }
    
    public void Resize(int newWidth, int newHeight)
    {
        Console.WriteLine($"调整图片 {fileName} 尺寸: {width}x{height} -> {newWidth}x{newHeight}");
        width = newWidth;
        height = newHeight;
        fileSize = width * height * 3;
    }
}

// PDF文档
public class PdfDocument : DocumentBase, IPrintableDocument
{
    private int pageCount;
    
    public PdfDocument(string fileName, int pageCount) : base(fileName)
    {
        this.pageCount = pageCount;
    }
    
    protected override void LoadContent()
    {
        content = $"PDF文档: {fileName},共 {pageCount} 页";
        fileSize = pageCount * 50000;  // 假设每页50KB
    }
    
    public override void Save()
    {
        Console.WriteLine($"保存PDF文档: {fileName}");
    }
    
    public override string GetContent()
    {
        return $"PDF文档,共 {pageCount} 页";
    }
    
    public void Print()
    {
        Console.WriteLine($"打印PDF文档: {fileName}");
        Console.WriteLine($"页数: {pageCount}");
    }
    
    public void PrintPreview()
    {
        Console.WriteLine($"PDF文档 {fileName} 打印预览:");
        Console.WriteLine($"总页数: {pageCount}");
        Console.WriteLine($"文件大小: {fileSize} 字节");
    }
    
    public int GetPageCount()
    {
        return pageCount;
    }
    
    public void AddPage()
    {
        pageCount++;
        fileSize += 50000;
        Console.WriteLine($"PDF文档 {fileName} 添加页面,当前页数: {pageCount}");
    }
}

// 文档管理器
public class DocumentManager
{
    private List<IDocument> documents;
    
    public DocumentManager()
    {
        documents = new List<IDocument>();
    }
    
    public void AddDocument(IDocument document)
    {
        documents.Add(document);
        Console.WriteLine($"添加文档: {document.FileName}");
    }
    
    public void OpenAllDocuments()
    {
        Console.WriteLine("打开所有文档:");
        foreach (var doc in documents)
        {
            doc.Open();
        }
    }
    
    public void SaveAllDocuments()
    {
        Console.WriteLine("保存所有文档:");
        foreach (var doc in documents)
        {
            doc.Save();
        }
    }
    
    public void PrintAllDocuments()
    {
        Console.WriteLine("打印所有可打印文档:");
        foreach (var doc in documents)
        {
            if (doc is IPrintableDocument printable)
            {
                printable.Print();
                Console.WriteLine();
            }
        }
    }
    
    public void EditTextDocuments(string newContent)
    {
        Console.WriteLine("编辑所有文本文档:");
        foreach (var doc in documents)
        {
            if (doc is IEditableDocument editable)
            {
                editable.AppendContent($"\n{newContent}");
            }
        }
    }
    
    public void ExportAllToHtml(string directory)
    {
        Console.WriteLine($"导出所有文档到HTML格式,目录: {directory}");
        foreach (var doc in documents)
        {
            if (doc is IExportableDocument exportable)
            {
                string htmlPath = Path.Combine(directory, Path.ChangeExtension(doc.FileName, ".html"));
                exportable.ExportToHtml(htmlPath);
            }
        }
    }
    
    public void ShowDocumentStatistics()
    {
        Console.WriteLine("文档统计:");
        Console.WriteLine($"总文档数: {documents.Count}");
        
        int editableCount = 0;
        int printableCount = 0;
        int exportableCount = 0;
        long totalSize = 0;
        int totalPages = 0;
        
        foreach (var doc in documents)
        {
            totalSize += doc.FileSize;
            
            if (doc is IEditableDocument) editableCount++;
            if (doc is IPrintableDocument printable)
            {
                printableCount++;
                totalPages += printable.GetPageCount();
            }
            if (doc is IExportableDocument) exportableCount++;
        }
        
        Console.WriteLine($"可编辑文档: {editableCount}");
        Console.WriteLine($"可打印文档: {printableCount}");
        Console.WriteLine($"可导出文档: {exportableCount}");
        Console.WriteLine($"总文件大小: {totalSize:N0} 字节");
        Console.WriteLine($"总页数: {totalPages}");
    }
}

static void DocumentSystemDemo()
{
    Console.WriteLine("=== 文档处理系统演示 ===");
    
    DocumentManager manager = new DocumentManager();
    
    // 添加不同类型的文档
    manager.AddDocument(new TextDocument("报告.txt"));
    manager.AddDocument(new ImageDocument("图表.jpg", 1920, 1080, "JPEG"));
    manager.AddDocument(new PdfDocument("手册.pdf", 25));
    manager.AddDocument(new TextDocument("笔记.txt"));
    
    Console.WriteLine();
    
    // 使用多态操作文档
    manager.OpenAllDocuments();
    Console.WriteLine();
    
    manager.ShowDocumentStatistics();
    Console.WriteLine();
    
    manager.EditTextDocuments("这是追加的内容。");
    Console.WriteLine();
    
    manager.SaveAllDocuments();
    Console.WriteLine();
    
    manager.PrintAllDocuments();
    
    manager.ExportAllToHtml("C:\\Exports");
    Console.WriteLine();
    
    // 演示特定类型的操作
    Console.WriteLine("=== 特定操作演示 ===");
    var textDoc = new TextDocument("新文档.txt");
    textDoc.Open();
    textDoc.SetContent("这是新的文档内容。");
    textDoc.AppendContent("\n这是追加的内容。");
    textDoc.PrintPreview();
    textDoc.Save();
}

本章小结

本章详细介绍了 C# 中的多态:

关键要点:

  • 多态定义:同一接口的多种实现,"一个接口,多种形态"
  • 多态类型:编译时多态(重载)和运行时多态(重写)
  • 实现方式:虚方法重写、抽象方法实现、接口实现
  • 多态优势:代码灵活性、可扩展性、可维护性

多态的实现机制:

  • 虚方法表(VMT):运行时方法分派
  • 后期绑定:运行时确定调用的方法
  • 类型检查:is 和 as 操作符

设计模式应用:

  • 策略模式:不同算法的多态实现
  • 模板方法模式:定义算法骨架,子类实现细节
  • 工厂模式:多态创建对象

最佳实践:

  • 面向接口编程,而不是面向实现
  • 合理使用抽象类和接口
  • 避免过度使用继承,考虑组合
  • 使用多态简化客户端代码
  • 遵循里氏替换原则

多态的好处:

  • 代码重用:统一的接口处理不同对象
  • 扩展性:添加新类型无需修改现有代码
  • 维护性:修改实现不影响客户端
  • 灵活性:运行时决定具体行为

注意事项:

  • 虚方法调用有性能开销
  • 过度使用多态可能降低代码可读性
  • 注意接口设计的稳定性
  • 合理使用 sealed 关键字

下一步: 在下一章中,我们将学习接口,深入理解 C# 中接口的定义、实现和应用。

延伸阅读

本站内容仅供学习和研究使用。