2

我正在巩固我对 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因为现在 B 型可以进入并更改该方法的预期功能,它不再关闭以进行修改(即确保它保持它的预期的行为,你必须改变它,以便它首先检查以确保我们只使用原始 A 对象)?

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

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

干杯

4

2 回答 2

0

我想说这并不是ShowClassType违反开放/封闭原则。只有 B 类违反了里氏替换原则。A 对扩展开放,对修改关闭。来自维基百科

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

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

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

于 2011-10-08T06:59:46.640 回答
0

我认为在这种使用环境中,它不违反 LSP 和 OCP。

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

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

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

于 2012-05-10T08:02:19.660 回答