c#中的继承和多态性
本文关键字:多态性 继承 | 更新日期: 2023-09-27 17:54:13
有一个简单的问题,程序将打印什么到控制台?
我从来没有想过我在这段代码中会犯这么多错误。它的行为与我的逻辑所期望的相反。
如果有人能告诉我每行印刷的原因,我将非常感激。
并且,实例化一个新的Circle并将其转换为Shape的意义是什么?为什么它也被视为椭圆?
Thank you so much
编辑:我被要求指定我期望的输出是什么。所以:
创建一个圆圈并将其转换为形状,我认为只有形状C'tor将被执行,因为它是一个形状。
调用super()的意义是什么如果它是自动完成的?椭圆函数执行形状函数中的代码
为什么x1.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
创建一个圆圈并将其转换为一个形状,我认为只有Shape C'tor会被执行,因为它是一个形状。
当你写new Circle()
时,它创建了Circle
的一个实例,所以它调用了Circle
的构造函数。然后再打石膏。实际上,在这种情况下,强制转换是多余的,因为Circle
已经是 Shape
。你只是将Circle
的实例赋值给Shape
类型的变量;这样,编译器就不知道变量的实际具体类型。Circle
实例实际上并没有被转换成其他任何东西。
如果super()是自动完成的,调用它有什么意义?椭圆C'tor执行形状C'tor中的代码。
我想你指的是base()
而不是super()
;不管怎样,你不会调用它,编译器会自动为你做。派生类的构造函数必须始终调用基类的构造函数来初始化基类的状态。在默认构造函数的情况下,你不需要显式地做,因为编译器会为你做。
为什么x1.Draw()被转换为形状正在执行椭圆的Draw()的代码?如您所见,x1、x2都输出了相同的消息。
这就是多态性的全部意义。在运行时,执行的方法取决于对象的实际具体类型。由于Ellipse
覆盖了Shape.Draw
方法,因此Ellipse
的实例执行的是Ellipse
的实现。
注意,在Circle
类中,您没有在Draw
方法上使用override
关键字;这意味着Circle.Draw
不覆盖Shape.Draw
,它只是一个不相关的方法,只是碰巧有相同的名称。它不会参与多态性,只有通过Circle
类型的变量调用它时才会调用它。
- 对于继承树中的每个类型(至少)必须调用一个构造函数。因此,在你的例子中,你可以看到每个构造函数的打印。
- 重定向到一个特定的(重载的)构造函数。
- 由于类的最后一个实现被调用。即使对象被强制转换,它仍然会调用最后一个类型的方法(除非通过
new
打破继承)。
-
创建一个圆圈并将其转换为形状,我只是在想将执行Shape C'tor,因为它是一个Shape。
正如您所说:您正在创建
Circle
并将其转换为Shape
。只有在创建对象的实例时才会调用构造函数。因此,您只需调用Circle
的构造函数。强制转换过程不调用任何构造函数 -
您总是需要使用
: base()
调用基构造函数。当有一个没有参数的基本构造函数时,编译器会为你添加: base()
(因为它很清楚)。您可以使用base()
来调用特定的基构造函数,该构造函数可能不是无参数的。 -
Draw()
方法你有在你的Circle
类只有当你有一个Circle
实例编译器知道。如果你有一个Ellipse
和一个Shape
,它们不知道自定义Draw
方法,因此从Ellipse
调用覆盖的
Draw
方法