理解Liskov和OCP之间的关系



我正在巩固我对Liskov替代原则和开合原则之间关系的理解。如果有人能证实我的推论并回答我下面的问题,那就太好了。

我有以下类。正如您所看到的,B是从A派生出来的,并且它正在重写DisplayMessage函数以改变行为。

public class A
{
    private readonly string _message;
    public A(string message)
    {
        _message = message;
    }
    public virtual void DisplayMessage()
    {
        Console.WriteLine(_message);
    }
}
public class B : A
{
    public B(string message) : base(message){}
    public override void DisplayMessage()
    {
        Console.WriteLine("I'm overwriting the expected behavior of A::DisplayMessage() and violating LSP >:-D");
    }
}

现在在我的引导程序中,ShowClassTypeis期望一个类型为A的对象,它应该有助于写出它是什么类类型。然而,B违反了LSP,所以当它的DisplayMessage函数被调用时,它会打印一个完全意想不到的消息,并且实际上干扰了ShowClassType的预期目的。

class Program
{
    static void Main(string[] args)
    {
        A a = new A("I am A");
        B b = new B("I am B");
        DoStuff(b);
        Console.ReadLine();
    }
    private static void ShowClassType(A model)
    {
        Console.WriteLine("What Class are you??");
        model.DisplayMessage();
    }
}

所以我的问题是,我是否正确地得出结论,ShowClassType现在违反了开闭原则,因为现在类型B可以进来并改变该方法的预期函数,它不再关闭以进行修改(即。为了确保它保持预期的行为,你必须改变它,以便它首先检查,以确保我们只与原始的A对象一起工作)?

或者,相反,这只是一个很好的例子,表明ShowClassType对于修改是关闭的,并且通过传递一个衍生类型(尽管一个LSP违反了一个),我们扩展了它的意思?

最后,如果基类不是抽象的,在基类上创建虚函数是不好的做法吗?通过这样做,我们不是在邀请派生类违反Liskov替换原则吗?

欢呼

我认为ShowClassType并没有违反开/闭原则。只有B类违反了李斯科夫替换原则。A为开放扩展,关闭修改。来自维基百科,

一个实体可以允许在不改变源代码的情况下修改其行为。

很明显,A的源代码没有被修改。也没有使用A的私有成员(这也违反了我书中的开放/封闭原则)。B严格使用A的公共接口,因此虽然遵循开/闭原则,但违反了Liskov替代原则。

最后一个问题本身就值得讨论。一个关于SO的相关问题在这里

我认为在这种情况下使用不违反LSP和OCP。

在我看来,ShowClassType不违反OCP:1. 函数不能破坏OCP,只有类架构才能做到这一点。2. 你可以在A的派生类中添加新的行为,这样它就不会破坏OCP

LSP呢?您的原因-用户不期望得到这个消息?但是他得到了一些信息!如果函数覆盖返回一些消息,我认为在你的代码的上下文中是可以的。如果函数,两个数字相加被覆盖,1+1返回678,这对我来说是不可预期的,而且很糟糕。但是,对于来自火星的物理学家来说,这可能是一个很好的答案。

不要在没有上下文的情况下分析问题!!你必须了解问题的全貌。当然还有

最新更新