用着名的Square / Rectangle示例打破Liskov原理给出了逻辑错误

时间:2017-12-15 21:59:52

标签: c# properties

我试图用Liskov原理来说明它打破它并且在下面的例子中期望当你为sqaure设置宽度时,长度自动设置为相同的长度,反之亦然。 但是,该区域返回0.在第二种情况下,我期望4x4 = 16,5x5 = 25。我究竟做错了什么?我怀疑它是在覆盖基类属性的方式。

using System;

public class Rectangle
{

    public int length { get; set; }
    public int breadth { get; set; }

    public int area() 
    {
        return length * breadth;
    }

}

public class Square : Rectangle { 


    public new int length;
    public new int breadth;

    public new int Length
    {
        get
        {
            return this.length;
        }
        set
        {
            this.breadth = this.length = value;
        }
    }


    public new int Breadth
    {
        get
        {
            return this.breadth;
        }
        set
        {
            this.breadth = this.length = value;
        }
    }
}


public class Program
{

    public static void Main()
    {

        Square s = new Square();
        s.length = 4;
        s.breadth = 5;
        int xx = s.area();
        Console.Write(xx);

        s.length = 5;
        s.breadth = 4;
        xx = s.area();
        Console.Write(xx);

    }



}

1 个答案:

答案 0 :(得分:3)

当您从base class继承时,您将继承其所有PublicProtected成员。在derived类中声明具有相同名称的新成员时。编译器会发出警告,询问您是否打算隐藏该成员?当您使用new关键字时,您告诉编译器:是的,我想隐藏此成员。 area方法的实施使用baseproperties,因此它不会看到您的公开Fields这就是您获得0的原因。 所以你的代码将成为:

public class Rectangle
{
    protected int _length;
    protected int _breadth;
    public virtual int Length
    {
        get { return _length; }
        set { _length = value; }
    }
    public virtual int Breadth {
        get { return _breadth; }
        set { _breadth = value; }
    }

    public int Area()
    {
        return Length * Breadth;
    }

}

public class Square : Rectangle
{

    public override int Breadth
    {
        get { return _breadth; }
        set { _breadth = value;
            _length = _breadth;
        }
    }
    public override int Length {
        get { return _length; }
        set { _length = value;
            _breadth = _length;
        }
    }
}

如果您想要override某些内容,则应在virtual的{​​{1}}类定义中添加base关键字。 在您的示例中,您将导致thing异常。因为每个属性设置者都会调用另一个。这就是为什么我使用受保护的成员来防止这种事情发生的原因。 This是您阅读有关继承的好参考资料