违反Liskov替代原则

时间:2015-03-09 09:16:18

标签: php oop solid-principles

以下这个例子如何违反Liskov的替代原则?我仍然无法理解它。对于我来说,在PHP OOP中的层次结构似乎没问题。

// Violation of Likov's Substitution Principle
class Rectangle
{
    protected $width;
    protected $height;

    public function setWidth($width){
        $this->width = $width;
    }

    public function setHeight($height){
        $this->height = $height;
    }


    public function getWidth(){
        return $width;
    }

    public function getHeight(){
        return $height;
    }

    public function getArea(){
        return $this->width * $this->height;
    }   
}

class Square extends Rectangle 
{
    public function setWidth($width){
        $this->width = $width;
        $this->height = $width;
    }

    public function setHeight($height){
        $this->width = $height;
        $this->height = $height;
    }

}

用法:

$Rectangle = new Rectangle();
$Rectangle->setWidth(5);
$Rectangle->setHeight(10);
echo $Rectangle->getArea(); // 50 --> correct

另:

$Rectangle = new Square();
$Rectangle->setWidth(5);
$Rectangle->setHeight(10);
echo $Rectangle->getArea(); // 100 --> correct

两者的重复是正确的。

那么,这段代码应该如何编写,以免违反Liskov的替代原则?

2 个答案:

答案 0 :(得分:3)

来自Liskov Substitution Principle

  

违反LSP的典型示例是派生的Square类   来自Rectangle类,假设存在getter和setter方法   宽度和高度。 Square类总是假设宽度   等于高度。如果在上下文中使用Square对象   在期望Rectangle的地方,可能会发生意外行为,因为   Square的尺寸不能(或者不应该)被修改   独立。 这个问题不容易修复:如果我们可以修改   Square类中的setter方法,以便它们保留   方形不变(即保持尺寸相等),然后是这些方法   会削弱(违反)矩形制定者的后置条件,   说明维度可以独立修改。违规   像这样的LSP,在实践中可能是也可能不是问题,   取决于实际的后置条件或不变量   期望由使用违反LSP的类的代码。可变性是一个   关键问题在这里。如果Square和Rectangle只有getter方法(即   它们是不可变对象),然后不会发生违反LSP的行为。

因此,如果你摆脱了setter,你的解决方案不再违反LSV。

答案 1 :(得分:0)

setWidth和setHeight已在父类中定义,并且根据Liskov替换原则,您不应修改派生类中父类的行为。当Square从Rectangle继承时,它使Square成为一个派生类,这意味着你不应该修改最初在Rectangle类中定义的那两个方法(setWith和setHeight)中的任何一个。

违反Liskov替代原则会产生不良影响。如果类层次结构增长,那么了解子类的行为将变得越来越复杂。其次,超类的单元测试对于子类永远不会成功。使用您的类型的代码必须明确了解派生类型的内部工作方式,以区别对待它们

我写了一篇文章解释了这个原则以及违反原则的后果。

http://isaacjarquin.github.io/software/2016/09/27/solid-liskov-substitution-principle.html