了解Liskov和OCP之间的关系

时间:2011-10-08 02:09:15

标签: liskov-substitution-principle open-closed-principle

我正在巩固对Liskov Substitutional Principal和Open Close Principal之间关系的理解。如果有人能够确认我的扣除并在下面回答我的问题,那就太棒了。

我有以下课程。如您所见,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现在违反了Open Close Principal,因为既然Type B可以进入并改变该方法的预期函数,它就不再关闭以进行修改(即确保它保持预期的行为,你必须改变它,以便它首先检查以确保我们只使用原始的A对象)?

或者,相反,这只是一个很好的例子,表明ShowClassType已关闭进行修改,并且通过传入派生类型(尽管LSP违反了一个),我们已经扩展了它的意图吗? / p>

最后,如果基类不是抽象的,那么在Base类上创建虚函数是不好的做法吗?通过这样做,我们不只是邀请衍生类违反Liskov替换校长吗?

干杯

2 个答案:

答案 0 :(得分:0)

我认为违反开放/封闭原则并非ShowClassType。 只有B级违反Liskov替代原则。 A是Open for extension,但已关闭以进行修改。 来自Wikipedia

  

实体可以允许修改其行为而不改变其源代码。

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

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

答案 1 :(得分:0)

我认为在这个使用环境中不违反LSP而不是OCP。

对于我的看法,ShowClassType不违反OCP: 1.功能不能破坏OCP,只有类架构才能做到这一点。 2.您可以从A中向派生类添加新行为 - 因此它不会破坏OCP

LSP怎么样?你的理由 - 用户不期望得到这条消息?但他收到了一些消息!如果函数重写返回一些消息,我认为在你的代码的这个上下文中是可以的。 如果函数,添加两个数字是覆盖,1 + 1返回678,这对我来说是不可预期的并且是坏的。但是,如果对于来自火星星球的物理科学家来说,它可以是一个很好的答案。

不要在没有所有背景的情况下分析问题!你必须全面了解问题。而且,当然