C#中的继承和多态

Inheritance and Polymorphism in C#

有一个简单的问题,程序将向控制台打印什么?

我从没想过我在这段代码上会犯这么多错误。它的表现与我的逻辑预期相反。

如果有人能告诉我打印每一行的原因,我将不胜感激。

另外,实例化一个新的 Circle 并将其转换为 Shape 是什么意思?为什么它也被视为椭圆?

非常感谢

编辑: 我被要求指定我期望的输出是什么。 所以:

  1. 创建一个 Circle 并将其转换为 Shape,我认为只有 Shape C'tor 会被执行,因为它是一个 Shape。

  2. 如果自动调用 super() 有什么意义? Ellipse C'tor 执行 Shape C'tor 中的代码。

  3. 为什么强制转换为Shape的x1.Draw()执行的是Ellipse的Draw()的代码?如您所见,x1,x2 都打印了相同的消息。

希望我更清楚,谢谢。

namespace ConsoleApplication2
{
    class Shape
    {
        public Shape()
        { 
            Console.WriteLine("SHAPE CTOR");
        }

        public virtual void Draw()
        {
            Console.WriteLine("Shape.Draw()");
        }
    }

    class Ellipse : Shape
    {
        public Ellipse()
        {
            Console.WriteLine("ELLIPSE CTOR");
        }

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

    class Circle : Ellipse
    {
        public static void Main()
        {
            Shape x1 = (Shape)new Circle();
            Ellipse x2 = (Ellipse)new Circle();
            Circle x3 = new Circle();
            x1.Draw();
            x2.Draw();
            x3.Draw();
        }

        public void Draw()
        {
            Console.WriteLine("CIRCLE DRAW");
        }
    }
}

输出:

SHAPE CTOR
ELLIPSE CTOR
SHAPE CTOR
ELLIPSE CTOR
SHAPE CTOR
ELLIPSE CTOR
ELLIPSE.Draw()
ELLIPSE.Draw()
CIRCLE DRAW
  1. 对于继承树中的每个类型(至少)必须调用一个构造函数。因此,您会在您的案例中看到每个构造函数打印。
  2. 重定向到特定的(重载)构造函数。
  3. 自上次调用 class 上的实现以来。即使对象被强制转换,它仍然会调用最后一个类型的方法(除非你通过new打破继承)。
  1. creating a Circle and casting it to a Shape, I was thinking that only the Shape C'tor will be executed, as it's a Shape.

    如您所说:您正在创建 Circle 并将其转换为 Shape。只有在创建对象实例时才会调用构造函数。因此,您只需调用 Circle 的构造函数。铸造过程不调用任何构造函数。

  2. 您始终需要使用 : base() 调用基础构造函数。当有一个参数较少的基本构造函数时,编译器将为您添加 : base() (因为它很清楚)。您可以使用 base() 来调用可能不是无参数构造函数的特定基础构造函数。

  3. Circle class 中的 Draw() 方法只有当您有 Circle 实例时编译器才会知道。在您的情况下,您有一个 Ellipse 和一个 Shape,它们不知道自定义 Draw 方法,因此从 [=19= 调用覆盖的 Draw 方法]

creating a Circle and casting it to a Shape, I was thinking that only the Shape C'tor will be executed, as it's a Shape.

当你写new Circle()时,它创建了一个Circle的实例,所以它调用了Circle的构造函数。演员阵容是在之后完成的。实际上,在这种情况下,转换是多余的,因为 Circle 已经 Shape。您只是将 Circle 的实例分配给 Shape 类型的变量;这样编译器就不知道变量的实际具体类型。 Circle 实例实际上并未转换为任何其他实例。

What's the point of calling super() if it's done automatically? the Ellipse C'tor executed the code in the Shape C'tor.

我假设你的意思是 base() 而不是 super();但无论如何,你并没有调用它,编译器会自动为你完成。派生 class 的构造函数必须始终调用基 class 的构造函数来初始化基 class 的状态。对于默认构造函数,您不需要显式地执行它,因为编译器会为您执行它。

Why does x1.Draw() which is casted to Shape is executing the code of Ellipse's Draw()? as you can see both x1,x2 printed the same message.

这就是多态性的全部意义所在。在运行时,执行的方法取决于对象的实际具体类型。由于 Ellipse 覆盖了 Shape.Draw 方法,因此为 Ellipse.

的实例执行的是 Ellipse 实现

请注意,在 Circle class 中,您没有在 Draw 方法中使用 override 关键字;这意味着 Circle.Draw 而不是 覆盖 Shape.Draw,它只是一个不相关的方法,恰好具有相同的名称。它不会参与多态,只有通过Circle.

类型的变量调用才会被调用