代码:
public class Car
{
public void DescribeCar()
{
Console.WriteLine("Car: Four wheels and an engine.");
ShowDetails();
}
public virtual void ShowDetails()
{
Console.WriteLine("Car: Standard transportation.");
}
}
public class ConvertibleCar : Car
{
public new void ShowDetails()
{
Console.WriteLine("ConvertibleCar: A roof that opens up.");
}
}
ConvertibleCar myCC = new ConvertibleCar();
myCC.DescribeCar();
myCC.ShowDetails();
//Output
Car: Four wheels and an engine.
Car: Standard transportation.
ConvertibleCar: A roof that opens
问题:我希望凭借我的理解,我应该得到" ConvertibleCar:一个屋顶而不是打开"在我的第二和第三行输出中。 在派生类上直接调用ShowDetails时,以及在基类中的方法中,它有什么不同。 PS:派生类中的showdetials设置为new。
答案 0 :(得分:0)
因为new
你有效地隐藏了ShowDetails
(实际上,在VB.NET中有Shadows个关键字。此外,使用new
,您可以将ShadowDetails
设为属性!
让我们创建两个类:Base和Derived:
class Base
{
public virtual int GetInt()
{
return 10;
}
}
class Derived : Base
{
public new int GetInt()
{
return 11;
}
}
现在,让我们测试一下:
Base b;
Derived d;
int x;
b = new Derived();
d = new Derived();
x = b.GetInt(); // x = 10 [Base.GetInt()]
x = d.GetInt(); // x = 11 [Derived.GetInt()]
如您所见,虽然已为b
分配了派生,但它仍指向Base
。
但是,让我们做一些完全不同的事情 - 让方法变成财产!
class Derived : Base
{
public new int GetInt
{
get { return 11; }
}
}
现在,当我们运行上一个测试代码时,我们会看到x = 10
:
x = d.GetInt(); // x = 10
但是,等等,我们在GetInt()
课程中没有Derived
方法!为什么编译代码?这很简单 - 因为我们使用GetInt
属性隐藏了GetInt()方法,现在从GetInt()
调用了Base
!为了使事情更加混乱,IntelliSense不会在GetInt()
变量上显示d
方法,但编译器会满意。要获得11,您需要致电财产:
x = d.GetInt;
您还可以将GetInt()
方法转换为委托:
class Derived : Base
{
public new delegate int GetInt();
}
并使用它:
Derived.GetInt getIntDelegate = () => 12;
Console.WriteLine(getIntDelegate()); // Prints 12
答案 1 :(得分:0)
用于隐藏基础成员/方法的new
关键字。所以
public new void ShowDetails()
{
Console.WriteLine("ConvertibleCar: A roof that opens up.");
}
ShowDetails
方法是new
类的ConvertibleCar
方法,基类ShowDetails
方法完全不同,并且不在固有链中。想象一下,您可以在ShowDetails2
类中定义类似ConvertibleCar
的方法名称。情况也是如此。
此外,如果您使用覆盖keyword
而不是new
,ConvertibleCar
类将覆盖ShowDetails
方法。
public class ConvertibleCar : Car
{
public override void ShowDetails()
{
Console.WriteLine("ConvertibleCar: A roof that opens up.");
}
}
输出将是;
Car: Four wheels and an engine.
ConvertibleCar: A roof that opens.
ConvertibleCar: A roof that opens.
答案 2 :(得分:0)
要获得预期的输出,请使用new
代替public override void ShowDetails()
{
Console.WriteLine("ConvertibleCar: A roof that opens up.");
}
:
new
如果您使用ShowDetails
,则阴影基类中的override
方法。这意味着只有在从派生类变量调用方法时才会使用派生类实现。
ShowDetails
做了不同的事情。如果覆盖public void DescribeCar()
{
Console.WriteLine("Car: Four wheels and an engine.");
ShowDetails(); <--------
}
,则只要对象的基础类型是派生类,无论变量的类型如何,都将始终使用派生类实现。
这解释了为什么第二行输出不同。第二行是从这一行产生的:
ShowDetails
this.ShowDetails
表示this
。 Car
的类型为ConvertibleCar
,但实际上是指ShowDetails
的对象。由于Car
被遮蔽,因此会调用this
的实现(因为Car
的类型为name
!)