[英]Inheritance and Polymorphism in C#
有一个简单的问题, 程序将在控制台上打印什么?
我从来没有想过我会像这段代码一样犯错。 它的行为与我的逻辑期望相反。
如果有人能启发每行打印的原因,我将非常感激。
而且,实例化一个新的Circle并将其转换为Shape的含义是什么? 为什么也将其视为椭圆形?
非常感谢
编辑:我被要求指定我期望输出是什么。 所以:
创建一个Circle并将其投射到Shape上,我当时认为只有Shape C'tor会被执行,因为它是Shape。
如果自动完成,调用super()有什么意义? 椭圆C'tor执行Shape C'tor中的代码。
为什么强制转换为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
创建一个Circle并将其投射到Shape上,我当时认为只有Shape C'tor会被执行,因为它是Shape。
当您编写new Circle()
,它将创建Circle
的实例,因此将调用Circle
的构造函数。 投射是在此之后完成的。 实际上,在这种情况下,投射是多余的,因为Circle
已经是 Shape
。 您只是将Circle
实例分配给Shape
类型的变量; 这样,编译器就不知道变量的实际具体类型。 Circle
实例实际上并未转换为其他任何实例。
如果自动完成,调用super()有什么意义? 椭圆C'tor执行Shape C'tor中的代码。
我假设你的意思是base()
而不是super()
; 但是无论如何,您不是在调用它,而是由编译器自动为您完成。 派生类的构造函数必须始终调用基类的构造函数来初始化基类的状态。 在默认构造函数的情况下,您不需要显式地执行此操作,因为编译器会为您执行此操作。
为什么强制转换为Shape的x1.Draw()执行Ellipse的Draw()代码? 如您所见,x1,x2都打印了相同的消息。
这就是多态的全部要点。 在运行时,执行的方法取决于对象的实际具体类型。 由于Ellipse
覆盖Shape.Draw
方法,它是Ellipse
是对于的一个实例中执行实现Ellipse
。
注意,在Circle
类中,您没有在Draw
方法上使用override
关键字。 这意味着Circle.Draw
不会覆盖Shape.Draw
,它只是恰好有相同的名称无关的方法。 它不会参与多态,只有通过Circle
类型的变量调用它时,它才会被调用。
new
中断继承)。 创建一个Circle并将其投射到Shape上,我当时认为只有Shape C'tor会被执行,因为它是Shape。
正如您所说的:您正在创建一个Circle
并将其转换为Shape
。 仅在创建对象实例时才调用构造函数。 因此,您只需调用Circle
的构造函数即可。 转换过程不调用任何构造函数。
您始终需要使用以下命令调用基本构造函数: base()
。 如果没有基本构造函数的参数,编译器将为您添加: base()
(因为其清除)。 您可以使用base()
来调用特定的基本构造函数,该构造函数可能不是无参数的。
仅当您具有Circle
实例时,编译器才知道您在Circle
类中具有的Draw()
方法。 在您的情况下,您有一个不知道自定义Draw
方法的Ellipse
和Shape
,因此可以从Ellipse
调用重写的Draw
方法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.