发布于 2026-01-06 0 阅读
0

SOLID:C# DEV 全球展示挑战赛中的里氏替换原则 (LSP) 由 Mux 呈现:展示你的项目!

SOLID:C# 中的里氏替换原则 (LSP)

由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!

介绍

里氏替换原则(LSP)是面向对象设计中的一个基础概念,由芭芭拉·里氏于1987年提出。它指出:

"Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program."

简而言之,派生类必须能够替代其基类,且不改变程序的预期行为。LSP 确保类层次结构的设计能够提高可重用性和可靠性。

遗产

LSP的关键方面

  1. 行为一致性:子类必须遵循其基类定义的行为。
  2. 无需担心:子类不应覆盖或削弱基类的任何功能。
  3. 契约:子类应遵守基类建立的“契约”(例如,前提条件和后置条件)。

违反 LSP 通常会导致代码脆弱,难以维护或扩展。

错误代码❌

public class Rectangle
{
    public virtual double Width { get; set; }
    public virtual double Height { get; set; }

    public double GetArea() => Width * Height;
}

public class Square : Rectangle
{
    public override double Width
    {
        set { base.Width = base.Height = value; }
    }

    public override double Height
    {
        set { base.Width = base.Height = value; }
    }
}

public class LSPViolationDemo
{
    public static void Main()
    {
        Rectangle rectangle = new Square(); // Substitution occurs here
        rectangle.Width = 4;
        rectangle.Height = 5; // Expecting Width=4 and Height=5 for a rectangle

        Console.WriteLine($"Area: {rectangle.GetArea()}"); // Output: 25, not 20!
    }
}
Enter fullscreen mode Exit fullscreen mode

出什么问题了?❌

Square用正方形代替Rectangle矩形违背了预期。矩形可以有不同的宽度和高度,但正方形的边长必须相等。因此,GetArea在这种情况下,结果是错误的。

遵循 LSP:更佳设计 ✔

遗产

为了遵循 LSP 原则,应避免强制子类执行不兼容的行为。在这种情况下,将子类分离RectangleSquare不同的层次结构中可以解决这个问题:

public abstract class Shape
{
    public abstract double GetArea();
}

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public override double GetArea() => Width * Height;
}

public class Square : Shape
{
    public double SideLength { get; set; }

    public override double GetArea() => SideLength * SideLength;
}

public class LSPAdherenceDemo
{
    public static void Main()
    {
        Shape rectangle = new Rectangle { Width = 4, Height = 5 };
        Shape square = new Square { SideLength = 4 };

        Console.WriteLine($"Rectangle Area: {rectangle.GetArea()}");
        Console.WriteLine($"Square Area: {square.GetArea()}");
    }
}
Enter fullscreen mode Exit fullscreen mode

为什么这种方法有效?

  1. 两者RectangleSquare源自形状,但它们独立运作,遵循各自的特定行为。
  2. LSP得以保留,因为替换过程尊重了每个类的预期行为。

跟随LSP的好处

  1. 提高了代码复用性:子类可以与现有代码无缝协作。
  2. 易于测试:遵循 LSP 的代码具有可预测性,更容易测试。
  3. 增强维护性:类之间的清晰边界使调试和扩展功能变得简单。

结论

里氏替换原则对于创建健壮且灵活的面向对象设计至关重要。通过确保子类可以与其基类互换使用而不会导致意外行为,您可以构建更易于维护和扩展的系统。在设计类层次结构时,请始终问自己:“这个子类能否在不改变程序行为的情况下替换其基类?”

遵循 LSP 不仅能加强你对 SOLID 原则的遵循,还能为可扩展、可维护的软件解决方案奠定基础。祝你编码愉快!

舞蹈

欢迎在LinkedIn上与我联系,也欢迎查看我的GitHub代码库:

文章来源:https://dev.to/extinctsion/solid-the-liskov-substitution-principle-lsp-in-c-1hl9