c# - 为什么需要将派生类的对象赋值给基类来调用方法?

标签 c# inheritance polymorphism overriding

我有一个名为 Shape 的基类和一个派生自 Shape 的派生类 Rectangle。

class Shape
{
    public virtual void Draw()
    { 
        //Draw the Shape
        Console.WriteLine("Draw the Shape");
    }
}
class Rectangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Draw Rectangle");
    }
}

我有一个非常基本的疑问,即在调用我的派生类的方法时我做了这样的事情。

Shape r1 = new Rectangle();
r1.Draw();

但是如果我想调用 Rectangle 类的方法,我总是可以这样做。

Rectangle r2 = new Rectangle();
r2.Draw();

我的问题是,当我们总是可以使用易于理解和实现的第二种方法时,为什么我们需要使用第一种方法。?

最佳答案

两种方法都是正确的,都可以工作。在这两种情况下,Rectangle 类的 Draw 方法都会被调用。

关于为什么要使用第一种方法的第一个场景是,当您有某种集合并且想要一次绘制它们时。假设您添加了更多派生类,例如 CircleTriangle,它们也覆盖了 Draw 的基本实现。那么以下仍然是一个有效的场景:

//We know that our collection will contain various shapes.
List<Shape> shapes = new List<Shape>();

//This is okay because all the specific shapes inherit from the Shape class.
shapes.Add(new Triangle());
shapes.Add(new Rectangle());
shapes.Add(new Circle());

//We can safely draw all shapes, because all shapes have a Draw-method.
//If they haven't implemented their own, the Draw-method of the Shape class will be called.
foreach(Shape shape in shapes)
  shape.Draw();

要记住的一件事是,在上面的示例中,我们将所有特定对象视为类型 Shape。这实质上意味着在该用法中,每个对象都不知道任何特定于类的实现。假设您向 Rectangle 添加了一个 NumberOfCorners 属性:

class Rectangle : Shape
{
    public Rectangle() {
        NumberOfCorners = 4;
    }

    public override void Draw()
    {
        Console.WriteLine("Draw Rectangle");
    }

    public int NumberOfCorners { get; set; };
} 

那么以下将不起作用,因为 Shape-class 没有 NumberOfCorners-property:

Shape shape = new Rectangle();
Console.WriteLine(shape.NumberOfCorners); //This will cause an error.

但是,特定实例仍然在 Rectangle 实例的深处,这意味着它可以工作:

Console.WriteLine((shape as Rectangle).NumberOfCorners); //This is fine, provided that shape is not null.

关于c# - 为什么需要将派生类的对象赋值给基类来调用方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24996500/

相关文章:

c# - 在 C# 中使用补充 Unicode 字符作为 char 文字

Java 无法调用 addAll() 将子类类型的数组列表添加到 <?扩展基类>

java - 如何模拟AppCompatActivity和ListActivity扩展行为

ruby-on-rails - Rails 逆多态关联

c# - 我可以在 C# DocumentDb 驱动程序中使用多态/继承吗

c++ - 从派生类实现基类构造函数的专门化的替代方法是什么?

c# - AcceptTcpClient() 和基于 TcpClient 的类

c# - Ninject BindFIlter<> 中 FilterScope 参数的用途是什么?

c# - 反序列化两个略有不同的JSON字符串(结构相同,名称不同)到同一个类

java - 具有可变参数列表的抽象方法