C#中如何将子类声明为超类类型

8
我很难找到一个令人满意的继承问题答案。为什么有时候要像这样声明一个子类型:
Shape myCircle = new Circle();

and this other times?

Circle myShape = new Circle();

在这里,Circle是Shape的一个子类。......

我看过很多面向对象编程的书籍,但它们对我来说似乎缺乏一致性和易于理解的解释。人们向我展示了Shapes类被实例化为圆形、正方形等的例子......但我不理解何时使用第一种声明方式和第二种声明方式。

3个回答

7

为了避免对特定类型的依赖,通常希望以多态的方式处理具体类的对象。例如,如果您创建一个意图绘制的Circle,并且Draw()Shape的方法,则最好将myCircle声明为Shape,以防以后决定用正方形替换它。

另一方面,如果您的目的是针对Circle执行特定操作,比如设置其半径,那么您需要将myCircle声明为Circle,因为SetRadius()可能在Shape上不可用。


4

也许你有一个形状列表,你并不特别关心这些形状是什么,因为你需要做的事情对所有形状都是通用的(比如绘制),你可以像这样将它们添加到列表中:

List<Shape> shapeList = new List<Shape>();
shapeList.Add(new Circle());
shapeList.Add(new Rectangle());
foreach (Shape shape in shapeList)
{
    shape.Draw();
}

这样,您可以访问实际上是不同类型但共享共同父级的对象上的形状的常见方法。然后,如果您想对圆形执行特定操作,您可以像这样使用相同的列表。

foreach (Shape shape in shapeList)
{
    if (!(shape is Circle)) continue;
    Circle circle = shape as Circle;
    circle.Radius = 100;
}

1
除了 @dasblinkenlight 的回答之外,您应该使用第一个声明而不是第二个声明,因为您想将 myCircle 对象的行为限制在 Circle 的成员中。
这是因为 CircleShape 的子类,这意味着 Circle 将继承 Shape 的所有成员,并且在某些情况下,因为您正在使用 C#(并且覆盖成员并不总是像 Java 中那样的规则),会被覆盖。
您不能做相反的事情:
Circle myCircle = new Shape();

原因在这里描述。

否则,如果您使用第二个声明,myCircle将是一个Circle对象,使用Circle可用的成员和方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接