请参阅下面的代码(C#):
Control button = new Button(100, 200, "Click Me!");
Control textBlock = new TextBlock(20, 20, "Hello World!");
List<Control> controls = new List<Control>();
controls.Add(button);
controls.Add(textBlock);
foreach (Control ctrl in controls)
{
ctrl.DrawMe(); //The objects will behave polymorphically, because they derive from
//a shared base class.
}
Control是我自己创建的抽象类。如果我将声明中的Control更改为等效的派生类(如下所示),我将获得完全相同的功能。这是为什么?在对抽象基类而不是派生类进行赋值时是否有任何区别?
Button button = new Button(100, 200, "Click Me!");
TextBlock textBlock = new TextBlock(20, 20, "Hello World!");
答案 0 :(得分:3)
如果您的Button
类有一个名为ButtonImage
的属性,但您的Control
类没有,则在通过控制列表进行计算时,您将无法访问它。
但是,你的对象会被降级&#34;降级&#34; (实际上)将其保存为Control
。
答案 1 :(得分:1)
然而,究竟是什么区别,也就是说,如果有的话。
嗯,当你调用virtual and overridden
方法时,这没有任何区别。
主要区别在于影子方法。
让我们考虑以下
class Control
{
public void DrawMe()
{ }
}
class Button
{
public new void DrawMe()
{ }
}
class TextBlock
{
public new void DrawMe()
{ }
}
foreach (Control ctrl in controls)
{
ctrl.DrawMe();//this will always call Control's version of DrawMe
}
此代码调用相应类的DrawMe
Button button = new Button(100, 200, "Click Me!");
TextBlock textBlock = new TextBlock(20, 20, "Hello World!");
button.DrawMe();//calls button's drawme and textblock will calls its version
正如评论中所指出的,我建议您详细了解polymorphism。
答案 2 :(得分:0)
我对OOP的理解不正确,随之而来的还有抽象方法如何与派生类相关。
根据here发现的MSDN文档,据说:
抽象方法声明引入了一个新的虚方法 没有提供该方法的实现。代替, 非抽象派生类需要提供自己的派生类 通过覆盖该方法实现。
因此,如果您像我一样实现了抽象方法,则需要通过重写该方法由派生类实现。由于抽象类无法实例化,并且抽象方法必须被其派生类覆盖,因此显然派生类的DrawMe()方法被调用。
<强>结论强>
功能是相同的,因为派生类的重写方法是唯一被调用的方法,也是唯一一个可以在这种情况下调用的方法。
对抽象类而不是派生类进行赋值时的区别在于编译器将尝试将实例化的类型隐式转换为抽象类的类型。但是,只有在编译器允许转换或实现适当的转换运算符时才能实现此目的(有关此内容的更多信息,请参阅MSDN文档here)。在这种情况下的转换没有区别,因为您正在利用的唯一调用是DrawMe() - 方法。