【问题标题】:Why there is an ability to override non abstract methods of base class [closed]为什么有能力覆盖基类的非抽象方法[关闭]
【发布时间】:2021-01-05 21:40:27
【问题描述】:

C++、php、python等OOD语言允许覆盖基类的非抽象方法。

但是这种能力允许违反 Liskov 替换原则。因为在这种情况下,不能在不改变程序行为的情况下用派生类替换程序中的基类。

为什么?

【问题讨论】:

  • 派生类的重点不是与基类有不同的行为吗?
  • 我会做一个友好的赌注:在 C++ 中,我将创建一个名为 base 的类,其方法名为“foo”。随意定义您想要的任何派生类,并将其传递给需要指针或引用base 类的某个函数,该函数将调用其foo 方法。你可以尝试任何你想要的东西,但无论你尝试什么,你都不会覆盖我对基类的foo 的调用。
  • 有时赋予人们使用 Git-R-Done 的能力也赋予人们在脚上开枪的能力。
  • 纯虚函数很容易违反 LSP:class Base { virtual float mul ( float x, float y ) = 0; }; class Sub { float mul ( float x, float y ) { return x + y; } };

标签: python php c++ oop


【解决方案1】:

但是这种能力允许违反 Liskov 替换原则。因为在这种情况下,不能在不改变程序行为的情况下用派生类替换程序中的基类。

这是对 Liskov 替换原则的错误描述。为了正确起见,将“不改变程序行为”更改为“不改变结果的正确性”(参见Wikipedia 以获取参考)。这个想法不是行为没有改变,而是改变的行为对于所讨论的对象是正确的。不同的对象可能有不同的行为被认为是正确的,因此需要重写非抽象方法。事实上,用另一个对象替换一个对象可能需要改变程序行为以使结果正确。

例如,考虑单击此网页上的内容。您单击的事物对应于对象,而单击对应于对该对象的onClick 虚函数的调用。响应您的点击的正确行为是什么?这取决于对象。如果对象是链接,则正确的行为是打开链接。如果对象是该段落,则正确的行为是忽略单击(假设是简单的单击;双击可能会选择一个词)。行为不同,但都是正确的。 Liskov 替换原则要求的是正确性,而正确性可能需要程序行为根据所讨论的对象而改变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 2011-09-16
    相关资源
    最近更新 更多