简单的C#OOP继承查询
鉴于以下类别:简单的C#OOP继承查询,c#,visual-studio,oop,inheritance,C#,Visual Studio,Oop,Inheritance,鉴于以下类别: interface IShape { void Draw(); } class Rectangle : IShape { public void Draw() { } } class Square : Rectangle { public new void Draw() { } } 有人能解释一下第二种抽签方法会发生什么吗 Rectangle rect = new Rectangle(); rect.Draw(); rect = new Squar
interface IShape
{
void Draw();
}
class Rectangle : IShape
{
public void Draw() { }
}
class Square : Rectangle
{
public new void Draw() { }
}
有人能解释一下第二种抽签方法会发生什么吗
Rectangle rect = new Rectangle();
rect.Draw();
rect = new Square();
rect.Draw();
一开始,我会说将调用Square类的Draw方法,但当我将其输入VS2013时,矩形类的Draw方法被调用。它将调用
Draw
的矩形版本
这是因为变量rect
在编译时的类型为Rectangle
。由于您已通过new
重写了Square
的Draw
方法,因此运行时无法在运行时查找Draw
的Square
版本-这将是在虚拟表或V表中的查找,在本例中不存在,因为Draw
不是Virtual
请注意,下面将调用Draw
Square sq = new Square();
sq.Draw();
因为sq
在编译时是已知的Square
如果要在矩形
内将绘制
设为虚拟
,并将新建
更改为覆盖
,则原始代码将调用正方形。绘制
。这是允许的,即使Draw
是接口方法的实现
也可以制作一种新的接口方法。考虑以下事项:
internal interface IShape
{
void Draw();
}
internal class Rectangle : IShape
{
public void Draw() { }
}
internal class Square : Rectangle, IShape
{
public new void Draw() { }
}
在这种情况下,代码
IShape rect = new Rectangle();
rect.Draw();
rect = new Square();
rect.Draw();
将调用第二个表单。在Square
类中,关键字new
告诉编译器这是一个全新的方法,恰好与继承的方法具有相同的签名。因为这是巧合,所以它不应该重写继承的方法
在这种情况下,当通过Square
变量调用Draw()
时,编译器将选择新方法。如果在这种情况下它没有选择新的方法,那么如果你仔细考虑的话,你根本没有办法调用它。如果要调用旧的Draw()
,仍然可以通过矩形
变量调用它(即使在同一实例上)
这称为,您可以在任何方法上执行。您不会经常需要它——如果可能的话,您应该避免它,因为虽然它的语义定义良好,但它会使您的源代码有点混乱
相反,如果希望表示这不是巧合,并且您有意使用相同的签名覆盖继承的方法,则应在新方法上使用关键字override
。在这种情况下,在对象上调用Draw()
时,无论从哪个变量调用它,都会得到用于创建该对象的类的Draw()
版本(new Square()
,new Rectangle()
,等等)
请记住,被重写的方法必须首先允许自己被重写。为此,必须首先将其标记为virtual
first-不能重写未标记为virtual
的方法
正如关键字所说,这被称为。您将经常看到并使用此方法,因为它启用了,这是面向对象编程的核心概念之一。如果Draw
方法是虚拟的,那么将使用对象的实际类型来确定要调用的方法,即Square.Draw
方法
由于该方法不是虚拟的,因此决定调用哪个方法的是引用的类型,即矩形.Draw
方法。当使用new
而不是override
时,该方法不会被覆盖,而是隐藏
class Animal
{
public virtual void MakeSound() { Console.WriteLine("Animal called"); }
}
class Dog : Animal
{
// Note: You can not use override and new in the same class, on
// the same method, with the same parameters. This is just to
// show when "new" takes effect, and when "override" takes effect.
public override void MakeSound()
{
Console.WriteLine("Animal's MakeSound called for dog");
}
public new void MakeSound()
{
Console.WriteLine("Dog's MakeSound called");
}
}
public static class Program
{
public static void Main(string[] args)
{
Dog dogAsDog = new Dog();
Animal dogAsAnimal = dogAsDog;
// prints "Dog's MakeSound called"
dogAsDog.MakeSound();
// prints "Animal's MakeSound called for dog"
dogAsAnimal.MakeSound();
}
}
由于已将其装箱为矩形,并且Square类隐藏而不是覆盖矩形的Draw(),因此第二个调用将执行矩形的Draw方法。研究覆盖与隐藏。这里有大量的资料。这实际上将开始深入探讨一些关于方法本身如何被调用和绑定的深层概念。将虚拟表格添加到您的研究中。这是一个对所有程序开放的问题。让优雅的代码战斗开始吧。