c# - 用著名的 Square/Rectangle 例子打破 Liskov 原则给出了一个逻辑错误

标签 c# properties

我试图用一个打破里氏原理的案例来说明它,并期望在下面的示例中,当您为正方形设置宽度时,长度会自动设置为相同的长度,反之亦然。 但是,该区域返回为 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);

    }



}

最佳答案

当您从 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 base 中的关键字类定义 thing . 在您的示例中,您将导致 StackOverFlow异常(exception)。因为每个属性 setter 都会调用另一个。这就是为什么我使用 protected 成员来防止这件事发生的原因。 This是你阅读继承的一个很好的引用

关于c# - 用著名的 Square/Rectangle 例子打破 Liskov 原则给出了一个逻辑错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47840413/

相关文章:

c# - 在 asp.net webservice 中调用 COM DLL 时出错

c# - 在协程中使用 Quaternion.RotateTowards() 旋转对象?

c# - 简单的if语句

java - 在 wicket 有没有办法直接读取本地化属性?

c# - 使用自定义编码或添加自定义字符

c# - 在 C# 中同步 SQL Server Compact 3.5

java - Git 或外部项目中的属性文件?

iOS:模态 viewController 如何记住它的属性?

Python:用属性覆盖成员?

java - Spring 启动和 ddl-auto 问题