【问题标题】:Is Liskov Substitution Principle violated in my example?在我的示例中是否违反了 Liskov 替换原则?
【发布时间】:2017-07-04 02:40:11
【问题描述】:

我想知道我应该如何组织我的两个班级。

  • 其中一个代表Knife:只是一个简单、坚固、基本的,就像一把菜刀。
  • 另一个是PocketKnife,其状态为打开关闭
class Knife{
  public function cut() {/* do the cutting */}
}
class PocketKnife extends Knife{
  private $opened = 0; // 0/1
  // ...
  public function cut() {
    if ($this->opened) {
      parent::cut();
    }
  }
}

我的代码中没有一个类是抽象的。

这个例子是否违反了 LSP?

在我看来确实如此,因为cut() 操作的后置条件应该是:

  1. 刀刃在切割后有点“老”
  2. 某些物体必须有一些损坏(例如,如果是某些游戏)

PocketKnife 处于其关闭 状态,我们不会有这些后置条件。还是我错了?

【问题讨论】:

    标签: oop solid-principles ooad liskov-substitution-principle


    【解决方案1】:

    它是否违反LSP,取决于“cut”的定义是什么(不应该是)。如果操作的后置条件是以下必须为真:

    1. 刀刃在切割后有点“老”
    2. 某些对象必须有一些损坏(例如,如果是某些游戏)

    那么,PocketKnife 在“关闭”时不满足这些条件。因此,PocketKnife 不能在任何地方都可以替代 Knife,并且 LSP 已损坏。

    如何解决?

    嗯,这取决于上下文,需要更多信息。但是,一个例子可能是这样的:

       class Knife{
          public function cut() {/* do the cutting */}
        }
    
        class PocketKnife extends Knife{
    
          private $opened = 0; // 0/1
          // ...
    
          public function cut() {
            if (!$this->opened) {
    
              // state is changed for cut to be performed.
              $this->opened = 1; 
    
              parent::cut();
    
              // may need to close again, after operation.
            }
          }
        }
    

    这样,LSP 就不会被破坏。同样,该示例只是给出了解决此类问题的方法的想法。

    【讨论】:

      【解决方案2】:

      Liskov 替换原则(最简单的 OOP 设计准则之一)简单地指出,任何子类型都必须可以替换其父类型,而不会破坏程序。

      如果你有一个像 someFunc(Knife k) 这样调用 k.cut() 的方法,并且你可以将 Knife 或 Pocketknife 或 WhatKnife 传递给该 someFunc 方法并让程序正常工作,那么你就没有违反 LSP。

      【讨论】:

      • 这并没有回答他的问题,它只是重申了 LSP 背后的想法/原则。他的代码违反了吗?为什么?
      猜你喜欢
      • 2020-02-03
      • 2015-01-01
      • 2021-11-17
      • 2012-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多