C#

时间:2015-06-07 20:28:13

标签: c# inheritance polymorphism

有一个简单的问题,该程序将如何打印到控制台?

我从来没有想过我会像这段代码那样错。它的行为与我的逻辑所期望的相反。

如果有人可以请指教每行打印的原因,我会非常感激。

而且,实例化一个新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都打印了相同的信息。

  4. 希望我更清楚,谢谢。

    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
    

3 个答案:

答案 0 :(得分:1)

  

创建一个Circle并将其转换为Shape,我认为只有Shape C&C才能执行,因为它是一个Shape。

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

  

如果自动完成,调用super()的重点是什么? Ellipse C&C来执行Shape C'中的代码。

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

  

为什么输入到Shape的x1.Draw()正在执行Ellipse' Draw()的代码?你可以看到x1,x2都打印了相同的信息。

这是多态性的全部观点。在运行时,执行的方法取决于对象的实际具体类型。由于Ellipse会覆盖Shape.Draw方法,因此对Ellipse的实例执行Ellipse实现。

请注意,在Circle课程中,您未使用override方法中的Draw关键字;这意味着Circle.Draw 覆盖Shape.Draw,它只是一个恰好具有相同名称的无关方法。它不会参与多态,只有在通过Circle类型的变量调用它时才会调用它。

答案 1 :(得分:0)

  1. 对于继承树中的每个类型(至少),必须调用一个构造函数。因此,您可以在案例中看到每个构造函数。
  2. 重定向到特定(重载)构造函数。
  3. 由于调用了类的最后一个实现。即使对象被转换,它仍然会调用最后一个类型的方法(除非你通过OUTPUT = "$(notdir $(CURDIR))" 打破继承)。

答案 2 :(得分:-1)

  1.   

    创建一个Circle并将其转换为Shape,我只想到了   Shape C&C将被执行,因为它是一个Shape。

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

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

  3. 只有Draw()实例时编译器才知道Circle类中的Circle方法。在您的情况下,您有一个Ellipse和一个Shape,他们不了解自定义Draw方法,因此可以从{{调用重写的Draw方法1}}