Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 为什么创建对象时使用其基本对象作为其类型,而创建对象时使用特定类型的对象_Oop - Fatal编程技术网

Oop 为什么创建对象时使用其基本对象作为其类型,而创建对象时使用特定类型的对象

Oop 为什么创建对象时使用其基本对象作为其类型,而创建对象时使用特定类型的对象,oop,Oop,我的问题很难翻译成英语,所以我会尽力的 在阅读一篇关于Liskov替换原理的文章时,我发现这个例子非常常见,可以说明LSP的重要性 有一个AreaCalculator类、一个Shape类和一个Rectangle类,该代码显示了在创建一个newrectangle作为其基础类但使用和子类型(如Rectangle newrectangle=new Square)时调用AreaCalculator的问题 我的问题是,如果我可以使用特定类型,为什么我要使用它的基类作为它的类型来创建一个对象?好处是什么 R

我的问题很难翻译成英语,所以我会尽力的

在阅读一篇关于Liskov替换原理的文章时,我发现这个例子非常常见,可以说明LSP的重要性

有一个AreaCalculator类、一个Shape类和一个Rectangle类,该代码显示了在创建一个newrectangle作为其基础类但使用和子类型(如Rectangle newrectangle=new Square)时调用AreaCalculator的问题

我的问题是,如果我可以使用特定类型,为什么我要使用它的基类作为它的类型来创建一个对象?好处是什么

Rectangle newRectangle = new Square(); vs  `Square newRectangle = new Square();`
此方法返回一个错误的平方面积

public void TwentyFor4X5RectangleFromSquare()
        {
            Rectangle newRectangle = new Square();
            newRectangle.Width = 4;
            newRectangle.Height = 5;
            Assert.AreEqual(20, AreaCalculator.CalculateArea(newRectangle));
        }



 public class AreaCalculator
    {
        public static int CalculateArea(Rectangle r)
        {
            return r.Height * r.Width;
        }

        public static int CalculateArea(Square s)
        {
            return s.Height * s.Height;
        }
    }

public class Rectangle
{
    public virtual int Height { get; set; }
    public virtual int Width { get; set; }
}

public class Square : Rectangle
{
    private int _height;
    private int _width;

    public override int Width
    {
        get { return _width; }
        set
        {
            _width = value;
            _height = value;
        }
    }

    public override int Height
    {
        get { return _height; }
        set
        {
            _width = value;
            _height = value;
        }
    }
}

得到错误答案的原因是,设置正方形对象的宽度或高度会同时设置正方形的宽度和高度

所以当你设定

newRectangle.Width = 4 
newRectangle.Height = 5 
然后你有一个4x4正方形,然后你设置

newRectangle.Width = 4 
newRectangle.Height = 5 
你有一个5x5的正方形 给你一个25的面积

如果删除此方法,则可以使用一个示例来说明为什么要将类设置为它的基类

   public static int CalculateArea(Square s)
    {
        return s.Height * s.Height;
    } 

您仍然可以计算正方形的面积,这是因为您的代码是根据合同而不是特定类型编写的。其中,所创建的接口是您建立的合同的一部分

例如,这个例子来自jeremy clarks的接口C

当您有一个用于人员的存储库,该存储库使用一个类person的实例创建人员并返回一个人员数组时,如下所示

Class PeopleRepository
{
   public Person[] GetPeople()
   {...}
}
如果您创建一个特定的类型,您可以这样做

PeopleRepository pr = new PeopleRepository()
Person[] people = pr.GetPeople()
foreach(var in people)
         //Do something
如果在repository类中更改了GetPeople的实现以返回列表和数组,那么上面的代码将无法工作。但是,如果您使用接口,它将工作例如

IEnumerable people;
people = = pr.GetPeople()
foreach(var in people)
             //Do something

正如amit所说,代码将更容易重构和维护

重构要容易得多。强制您使用所需内容,而不是临时实现,从而为您提供更好的代码。允许不知道实际类型是什么,只有基类型对方法非常有用arguments@amit你知道我可以用来了解更多的文档吗。我还是不明白这有什么好处。@gorilla谢谢。我知道我得到了错误的答案,我的问题是,为什么更好地使用它的基类型作为its类型来创建对象,而不是我想在特定代码中使用的类型。