我认为子类可以覆盖非虚拟的父方法
class Parent {
public void hello() {
Console.WriteLine("Hello Parent");
}
}
class Child:Parent{
public void hello() {
Console.WriteLine("Hello Child");
}
static void Main() {
Parent p = new Child();
Child c = new Child();
p.hello(); // Hello Parent
c.hello(); // Hello Child
}
}
那么在父方法中虚拟和非虚拟之间有什么不同?
答案 0 :(得分:1)
在C#中,virtual methods support polymorphism,使用virtual和override关键字的组合。使用基类方法上的virtual关键字和派生类中方法的override关键字,这两种方法都被认为是虚拟的。
没有virtual或override关键字或具有new关键字的方法被认为是非虚拟的。
当在对象上调用虚方法时,该对象的运行时类型用于确定要使用的方法的哪个实现。
当在对象上调用非虚方法时,该对象的编译时类型用于确定要使用的方法的哪个实现。
在这种情况下,您可以使用new
关键字
public new void hello()
{
Console.WriteLine("Hello Child");
}
取自here
的文字答案 1 :(得分:0)
只能覆盖标记为virtual
的方法。其他人可以隐藏(使用new
关键字),这根本不是同一件事。
class Parent
{
public virtual int MyMethod()
{
return 1;
}
}
class Child : Parent
{
public override int MyMethod()
{
return 2;
}
}
class OtherChild : Parent
{
public new int MyMethod()
{
return 3;
}
}
// ...
Parent p = new Parent();
Parent c = new Child();
Parent oc = new OtherChild();
int result;
result = p.MyMethod(); // will return 1
result = c.MyMethod(); // will return 2
result = oc.MyMethod(); // will return 1
在上面的示例中,请注意每个变量都声明为Parent
。在第一个上调用MyMethod
将只返回基本实现。在第二个上调用它会调用Child
类中的覆盖。然而,第三个被宣布为Parent
,并不知道MyMethod
类中OtherChild
的实现,并且调用它所知道的那个:Parent
。
如果您想了解有关多态性的更多信息,建议您查看维基百科上的这篇文章:
答案 2 :(得分:0)
子类中的方法hello()不会覆盖父类中的hello方法。子方法只是隐藏父类中的实现
答案 3 :(得分:0)
有很大的不同。我建议你read this and carefully go through the examples。
总而言之,您正在处理的是方法重写与方法隐藏之间的区别。
方法重写允许基类型访问派生类型的重写功能的行为。这是您在派生类型的方法上使用override
关键字时所执行的操作,其中基本类型的方法使用virtual
关键字标记。另一方面,在基础类型的方法未标记为virtual
的情况下使用相同的方法签名就是所谓的方法隐藏。实际上,您可以在不使用new
关键字的情况下执行此操作,但会收到编译器警告。
方法隐藏失去了方法重写提供的多态性好处,因为派生类的方法将使用隐藏方法的“新”行为,但基类将继续使用基类的方法版本。方法隐藏的结果看起来非常不直观,并且通常在OOP中效果是不合需要的,但它确实有它的位置。例如,我最喜欢使用方法隐藏的一种方法是allow for easier unit testing of protected methods。
以下代码示例直接来自第一个链接,并简洁地说明了方法重写与方法隐藏不同的方法之一:
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
答案 4 :(得分:0)
问题在于您的测试代码,虚拟的力量就是这样(如果您将方法设置为虚拟):
Parent p = new Parent();
Parent c = new Child();
Console.WriteLine(p.hello()); //Prints Hello Parent
Console.WriteLine(c.hello()); //Prints Hello Child
如果你保持unvirtual,两行都会打印hello parent
有点现实世界的例子是:
Vehicle p = new Vehicle();
Vehicle c = new Car();
Console.WriteLine(p.Drive()); //Prints "Default Vehicle"
Console.WriteLine(c.Drive()); //Prints "Car"