C#中的继承不良示例

时间:2012-02-16 22:38:42

标签: c# inheritance

我正在阅读一个简单遗传的例子,并且遇到了一个基本概念:一个正方形是一个基本类型,一个矩形是从一个正方形派生出来的。

设置方形尺寸的示例使用了名为Size的属性。 然后,矩形的示例继续使用WidthHeight

这在我的头脑中没有意义,所以我编码了。

问题似乎是在访问rectangle时,总会出现一个名为“Size”的令人困惑的属性。

我做对了吗?或者有没有办法在查看Size时隐藏其他类看rectangle

public class square
{
    public int Size { get; set; }
    public square(int size)
    {
        this.Size = size;
    }
}

public class rectangle : square
{
    public int Width { get { return base.Size; } set { base.Size = value; } }

    public int Height { get; set; }

    public rectangle(int width, int height)
        : base(width)
    {
        Height = height;
    }
}

8 个答案:

答案 0 :(得分:13)

你是100%正确的,这是向后继承。相反,您应该从Square类继承Rectangle类,因为正方形是一种特殊的矩形。

然后,你会得到像

这样的东西
public class Rectangle
{
    public int Width { get; private set; }
    public int Height { get; private set; }

    public Rectangle(int width, int height)
    {
        if (width <= 0 || height <= 0)
            throw new ArgumentOutOfRangeException();
        Width = width;
        Height = height;
    }
}

public class Square : Rectangle
{
    public int Size
    {
        get
        {
            return Width;
        }
    }

    public Square(int size)
        : base(size, size)
    {
    }
}

答案 1 :(得分:8)

问题是矩形正方形 - 您甚至不能说SquareRectangle因为这会导致很多问题Rectangle(通常)提供了独立设置宽度和高度的方法 - 这将由Square 约束 - 这是对Liskov substition principle.的经典违规 - 引自维基百科:

  

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

答案 2 :(得分:3)

  

遇到了一个基本思想,即一个正方形是一个基本类型,一个矩形是从一个正方形派生出来的。

问题是这是假的 -

正方形是特定类型的矩形,但矩形不是正方形。

话虽这么说,制作方形继承矩形也很危险,因为你最终会出现意想不到的情况。这是common violation of the Liskov Substitution Principle,这就是让SquareRectangle同时实现公共基类(例如Shape)更好的原因,它只包含共享的属性这两个类,例如AreaBounds等等。

答案 3 :(得分:2)

我认为问题是几何问题: - )

矩形不是正方形。 正方形是一个矩形。

你应该反转继承,你会发现矩形只有Width和Height,而square有一个名为Size的附加属性。

再见 马可

答案 4 :(得分:0)

正方形总是一个矩形,但矩形并不总是正方形 - 因此Rectangle 应该是Square的父级,而不是相反。< / p>

答案 5 :(得分:0)

几何101:正方形是矩形,但矩形不是正方形。

答案 6 :(得分:0)

Square和Rectangle是违反Liskov substitution principle的典型示例。在这个原则中,两者都没有直接相关,但可能与一个形状有关,例如。

例如:

public class Rectangle
{
     public int width {get;set;}
     public int height {get;set;}
     public int Area() { return width * height; }
}

public class Square : Rectangle
{
    public override int width
    {
        get { return base.width; }
        set { base.height = value; base.width = value; }
    }

    //... etc ...
}

[Test]
public void Rectangles_area_should_equal_length_times_width()
{
    Rectangle r = new Square();
    r.height = 10;
    r.width  = 15;

    Assert.That(r.Area() == 150); // Fails
}

你看到了问题吗?从基类引用方块时,行为会以意外方式更改。正确的解决方案是Square和Rectangle是兄弟姐妹(Shape的孩子),而不是父母/孩子。

答案 7 :(得分:0)

请参阅有关隐藏继承成员的问题,您可以使用new修饰符:

public class Rectangle : Square {
     private new int Size { get; set; }
     ...
}