根据this类似的StackOverflow问题和其他文章,默认情况下C#方法是“非虚拟的”,我认为这意味着你不能在派生类中覆盖它们。
如果这是真的,你可以向我解释一下,在下面的例子中,我如何能够在Child类中实现继承Base类的属性LastName,而不将属性标记为“virtual”inh基类? Child.LastName属性是否“隐藏”(VB“阴影”)基类中的相同属性?如果是这样,为什么Child.LastName pproperty中没有使用“新”关键字来表示这个?
此测试示例似乎向我建议默认情况下方法和虚拟,并且在LastName属性的情况下,隐含“overrrides”,但我很确定这不是案子。
我错过了什么?
public class BaseClass
{
private string _FirstName;
public virtual string FirstName {
get { return _FirstName; }
set { _FirstName = value; }
}
private string _LastName;
public string LastName {
get { return _LastName; }
set { _LastName = value; }
}
public void Go()
{
MessageBox.Show("Going at default speed in Base Class");
}
public void Go(int speed)
{
MessageBox.Show("Going at " + speed.ToString() + " in Base Class");
}
}
public class Child : BaseClass
{
public override string FirstName {
get { return "Childs First Name"; }
set { base.FirstName = value; }
}
public string LastName {
get { return "Child's Last Name"; }
set { base.LastName = value; }
}
public void Go()
{
MessageBox.Show("Going in Child Class");
}
public void Go(int speed)
{
MessageBox.Show("Going at " + speed.ToString() + " in Child Class");
}
}
答案 0 :(得分:4)
默认情况下,C#中的方法不是虚拟的。 Child类中的LastName从BaseClass中隐藏LastName。据我所知,这段代码甚至可以编译,但编译器会提供警告,告诉我应该使用新的关键字。
答案 1 :(得分:3)
默认情况下,它们是非虚拟的。
子类隐藏基础的LastName
属性。
如果你写:
BaseClass b = new Child(...);
Console.WriteLine(b.LastName);
您将看到调用基础实现。
编译上述代码时,编译器会向您发出警告。标记将基础成员隐藏为new
的成员的标准做法。
public new string LastName {
get { return "Child's Last Name"; }
set { base.LastName = value; }
}
这是一个非常常见的C#编程面试问题:)
答案 2 :(得分:2)
对多态性的充分理解将清除这一点:
Polymorphism (C# Programming Guide)
用新成员隐藏基类成员
如果希望派生成员与基类中的成员具有相同的名称,但您不希望它参与虚拟调用,则可以使用new关键字。 new关键字放在要替换的类成员的返回类型之前。以下代码提供了一个示例:
public class BaseClass
{
public void DoWork() { WorkField++; }
public int WorkField;
public int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public new void DoWork() { WorkField++; }
public new int WorkField;
public new int WorkProperty
{
get { return 0; }
}
}
通过将派生类的实例强制转换为基类的实例,仍然可以从客户端代码访问隐藏的基类成员。例如:
DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Calls the old method.
阻止派生类覆盖虚拟成员
虚拟成员无限期地保持虚拟,无论虚拟成员与最初声明它的类之间声明了多少个类。如果类A声明一个虚拟成员,而类B派生自A,而类C派生自B,则类C继承虚拟成员,并且可以选择覆盖它,无论类B是否声明了该成员的覆盖。以下代码提供了一个示例:
public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}
派生类可以通过将覆盖声明为密封来停止虚拟继承。这需要在类成员声明中将override关键字放在override关键字之前。以下代码提供了一个示例:
public class C : B
{
public sealed override void DoWork() { }
}
在前面的示例中,DoWork方法不再是从C派生的任何类的虚拟方法。对于C的实例,它仍然是虚拟的,即使它们被转换为类型B或类型A.密封方法可以由派生替换使用new关键字的类,如下例所示:
public class D : C
{
public new void DoWork() { }
}
在这种情况下,如果使用D类型的变量在D上调用DoWork,则会调用新的DoWork。如果使用类型C,B或A的变量来访问D的实例,则对DoWork的调用将遵循虚拟继承的规则,将这些调用路由到C类上的DoWork实现。
答案 3 :(得分:0)
new
关键字在继承层次结构链中制动虚拟覆盖。