了解Liskov和OCP之间的关系

发布于 2024-12-08 21:40:56 字数 1522 浏览 2 评论 0原文

我正在巩固我对里氏替代校长和开闭校长之间关系的理解。如果有人能证实我的推论并回答我的问题,那就太好了。

我有以下课程。如您所见,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 类型的对象,该对象应该有助于写出它是什么类 Type。然而,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)我们已经扩展了它的用途?

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

干杯

I am solidifying my understanding of the relationship between Liskov Substitutional Principal and Open Close Principal. If anybody could confirm my deductions and answer my questions below that would be great.

I have the following classes. As you can see, B is derived from A and it is overriding the DisplayMessage function in order to alter the behavior.

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");
    }
}

Now in my bootstrap program, ShowClassTypeis expecting an object of Type A which should helpfully write out what class Type it is. However B is violating LSP so when it's DisplayMessage function is called it prints a completely unexpected message and essentially interferes with the intended purpose of 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();
    }
}

So my question is, am I right to conclude that ShowClassType is now violating the Open Close Principal because now that Type B can come in and change the expected function of that method, it is no longer closed for modification (ie. to ensure it maintains it's expected behaviour you would have to alter it so that it first checks to make sure we are only working with an original A object)?

Or, inversely is this just a good example to show that ShowClassType is closed for modification and that by passing in a derived type (albeit a LSP violating one) we have extended what it is meant to do?

Lastly, is it bad practice to create virtual functions on Base classes if the base class is not abstract? By doing so, are we not just inviting derived classes to violate the Liskov Substitution principal?

Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

皓月长歌 2024-12-15 21:40:56

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

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

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

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

I'd say it's not ShowClassType that is violating the Open/Closed Principle.
It's only class B that is violating the Liskov Substitution Principle. A is Open for extension, but closed for modification.
From Wikipedia,

an entity can allow its behaviour to be modified without altering its source code.

It's obvious that the source code of A is not modified. Nor are private members of A being used (which would also be a violation of the Open/Closed principle in my book). B strictly uses the public interface of A, so although the Open/Closed principle is obeyed the Liskov Substitution Principle is violated.

The last question is worth a discussion in and of itself. A related question on SO is here.

小忆控 2024-12-15 21:40:56

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

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

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

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

I think it is not violate not LSP and not OCP in THIS context of using.

For my opinion, ShowClassType not violation OCP:
1. Function can not break OCP, only class architecture can do this.
2. You can add new behaviours to derived classes from A - so it do not break OCP

What about LSP? Your reason - user not expected get this message? But he got some message! If function overriding returns some message i think is ok in THIS context of your code.
If function, that add two numbers is overrides, and 1+1 returns 678 it not expectable for me and is bad. BUT, if for scientist of Physics from Mars planet it can be good answer.

DO NOT ANALYSE PROBLEM WITHOUT ALL CONTEXT!!! You must get whole picture of problem. And, of course

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文