多态 #

一、多态概述 #

多态是指同一操作作用于不同对象时,产生不同的行为。C#支持两种多态:

类型 说明
编译时多态 方法重载、运算符重载
运行时多态 虚方法、抽象方法、接口

二、编译时多态 #

2.1 方法重载 #

csharp
public class Calculator
{
    public int Add(int a, int b) => a + b;
    public double Add(double a, double b) => a + b;
    public int Add(int a, int b, int c) => a + b + c;
    public string Add(string a, string b) => a + b;
}

var calc = new Calculator();
calc.Add(1, 2);
calc.Add(1.5, 2.5);
calc.Add(1, 2, 3);
calc.Add("Hello", "World");

2.2 运算符重载 #

csharp
public struct Point
{
    public int X { get; }
    public int Y { get; }
    
    public Point(int x, int y) => (X, Y) = (x, y);
    
    public static Point operator +(Point a, Point b)
        => new Point(a.X + b.X, a.Y + b.Y);
    
    public static Point operator -(Point a, Point b)
        => new Point(a.X - b.X, a.Y - b.Y);
    
    public static bool operator ==(Point a, Point b)
        => a.X == b.X && a.Y == b.Y;
    
    public static bool operator !=(Point a, Point b)
        => !(a == b);
    
    public override string ToString() => $"({X}, {Y})";
}

var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
var p3 = p1 + p2;

三、运行时多态 #

3.1 虚方法 #

csharp
public class Animal
{
    public string Name { get; set; }
    
    public virtual void MakeSound()
    {
        Console.WriteLine("动物发出声音");
    }
    
    public virtual string GetInfo()
    {
        return $"动物:{Name}";
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("汪汪汪");
    }
    
    public override string GetInfo()
    {
        return $"狗:{Name}";
    }
}

public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("喵喵喵");
    }
    
    public override string GetInfo()
    {
        return $"猫:{Name}";
    }
}

3.2 多态调用 #

csharp
Animal animal1 = new Dog { Name = "旺财" };
Animal animal2 = new Cat { Name = "咪咪" };

animal1.MakeSound();
animal2.MakeSound();

Console.WriteLine(animal1.GetInfo());
Console.WriteLine(animal2.GetInfo());

3.3 集合中的多态 #

csharp
var animals = new List<Animal>
{
    new Dog { Name = "旺财" },
    new Cat { Name = "咪咪" },
    new Dog { Name = "大黄" }
};

foreach (var animal in animals)
{
    animal.MakeSound();
}

四、抽象类多态 #

4.1 抽象类定义 #

csharp
public abstract class Shape
{
    public string Name => GetType().Name;
    
    public abstract double Area { get; }
    public abstract double Perimeter { get; }
    
    public virtual void Display()
    {
        Console.WriteLine($"{Name}: 面积={Area:F2}, 周长={Perimeter:F2}");
    }
}

4.2 具体实现 #

csharp
public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }
    
    public override double Area => Width * Height;
    public override double Perimeter => 2 * (Width + Height);
}

public class Circle : Shape
{
    public double Radius { get; set; }
    
    public override double Area => Math.PI * Radius * Radius;
    public override double Perimeter => 2 * Math.PI * Radius;
}

public class Triangle : Shape
{
    public double A { get; set; }
    public double B { get; set; }
    public double C { get; set; }
    
    public override double Area
    {
        get
        {
            double s = Perimeter / 2;
            return Math.Sqrt(s * (s - A) * (s - B) * (s - C));
        }
    }
    
    public override double Perimeter => A + B + C;
}

4.3 使用多态 #

csharp
var shapes = new List<Shape>
{
    new Rectangle { Width = 5, Height = 3 },
    new Circle { Radius = 4 },
    new Triangle { A = 3, B = 4, C = 5 }
};

double totalArea = 0;
foreach (var shape in shapes)
{
    shape.Display();
    totalArea += shape.Area;
}

Console.WriteLine($"总面积:{totalArea:F2}");

五、接口多态 #

5.1 接口定义 #

csharp
public interface IDrawable
{
    void Draw();
}

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

public interface IColorable
{
    string Color { get; set; }
}

5.2 接口实现 #

csharp
public class Rectangle : Shape, IDrawable, IResizable, IColorable
{
    public double Width { get; set; }
    public double Height { get; set; }
    public string Color { get; set; }
    
    public override double Area => Width * Height;
    public override double Perimeter => 2 * (Width + Height);
    
    public void Draw()
    {
        Console.WriteLine($"绘制{Color}矩形 {Width}x{Height}");
    }
    
    public void Resize(double factor)
    {
        Width *= factor;
        Height *= factor;
    }
}

public class Circle : Shape, IDrawable, IColorable
{
    public double Radius { get; set; }
    public string Color { get; set; }
    
    public override double Area => Math.PI * Radius * Radius;
    public override double Perimeter => 2 * Math.PI * Radius;
    
    public void Draw()
    {
        Console.WriteLine($"绘制{Color}圆形 半径{Radius}");
    }
}

5.3 接口多态调用 #

csharp
var drawables = new List<IDrawable>
{
    new Rectangle { Width = 5, Height = 3, Color = "红色" },
    new Circle { Radius = 4, Color = "蓝色" }
};

foreach (var drawable in drawables)
{
    drawable.Draw();
}

var resizables = new List<IResizable>
{
    new Rectangle { Width = 5, Height = 3 },
};

foreach (var resizable in resizables)
{
    resizable.Resize(2);
}

六、多态设计模式 #

6.1 策略模式 #

csharp
public interface IDiscountStrategy
{
    decimal CalculateDiscount(decimal amount);
}

public class NoDiscount : IDiscountStrategy
{
    public decimal CalculateDiscount(decimal amount) => 0;
}

public class PercentageDiscount : IDiscountStrategy
{
    private readonly decimal _percentage;
    
    public PercentageDiscount(decimal percentage) => _percentage = percentage;
    
    public decimal CalculateDiscount(decimal amount) => amount * _percentage / 100;
}

public class FixedDiscount : IDiscountStrategy
{
    private readonly decimal _fixedAmount;
    
    public FixedDiscount(decimal fixedAmount) => _fixedAmount = fixedAmount;
    
    public decimal CalculateDiscount(decimal amount) => Math.Min(_fixedAmount, amount);
}

public class PriceCalculator
{
    private IDiscountStrategy _discountStrategy;
    
    public PriceCalculator(IDiscountStrategy strategy)
    {
        _discountStrategy = strategy;
    }
    
    public void SetStrategy(IDiscountStrategy strategy)
    {
        _discountStrategy = strategy;
    }
    
    public decimal CalculateFinalPrice(decimal originalPrice)
    {
        return originalPrice - _discountStrategy.CalculateDiscount(originalPrice);
    }
}

6.2 工厂模式 #

csharp
public abstract class Document
{
    public abstract void Open();
    public abstract void Save();
}

public class WordDocument : Document
{
    public override void Open() => Console.WriteLine("打开Word文档");
    public override void Save() => Console.WriteLine("保存Word文档");
}

public class PdfDocument : Document
{
    public override void Open() => Console.WriteLine("打开PDF文档");
    public override void Save() => Console.WriteLine("保存PDF文档");
}

public class ExcelDocument : Document
{
    public override void Open() => Console.WriteLine("打开Excel文档");
    public override void Save() => Console.WriteLine("保存Excel文档");
}

public static class DocumentFactory
{
    public static Document Create(string type)
    {
        return type.ToLower() switch
        {
            "word" => new WordDocument(),
            "pdf" => new PdfDocument(),
            "excel" => new ExcelDocument(),
            _ => throw new ArgumentException($"未知文档类型:{type}")
        };
    }
}

Document doc = DocumentFactory.Create("word");
doc.Open();
doc.Save();

七、实战示例 #

7.1 支付系统 #

csharp
public interface IPaymentMethod
{
    bool ProcessPayment(decimal amount);
    string Name { get; }
}

public class CreditCardPayment : IPaymentMethod
{
    public string Name => "信用卡";
    public string CardNumber { get; set; }
    
    public bool ProcessPayment(decimal amount)
    {
        Console.WriteLine($"信用卡支付:{amount:C}");
        return true;
    }
}

public class WeChatPayment : IPaymentMethod
{
    public string Name => "微信支付";
    
    public bool ProcessPayment(decimal amount)
    {
        Console.WriteLine($"微信支付:{amount:C}");
        return true;
    }
}

public class AlipayPayment : IPaymentMethod
{
    public string Name => "支付宝";
    
    public bool ProcessPayment(decimal amount)
    {
        Console.WriteLine($"支付宝支付:{amount:C}");
        return true;
    }
}

public class PaymentProcessor
{
    private readonly List<IPaymentMethod> _methods = new();
    
    public void AddMethod(IPaymentMethod method) => _methods.Add(method);
    
    public IEnumerable<string> GetAvailableMethods() => _methods.Select(m => m.Name);
    
    public bool Process(string methodName, decimal amount)
    {
        var method = _methods.FirstOrDefault(m => m.Name == methodName);
        return method?.ProcessPayment(amount) ?? false;
    }
}

八、总结 #

多态要点:

类型 说明
编译时多态 重载
运行时多态 虚方法、抽象类、接口
virtual/override 虚方法重写
abstract 抽象方法强制实现

下一步,让我们学习抽象类!

最后更新:2026-03-26