有人可以解释这两个例子之间的区别吗?
A类
protected virtual string GetData()
B类
private override string GetData()
以下内容:
A类
protected string GetData()
B类
private string GetData()
假设'B级'继承自'A级'。
我总是假设你需要在超类中使用virtual
而在子类中使用override
如果你想要覆盖一个方法,但我尝试删除关键字并编译好的程序。究竟有什么区别?如果有的话?
答案 0 :(得分:5)
您展示的第二个示例隐藏了父级的GetData,它不会覆盖它。
示例:
private class Base
{
public virtual void Test()
{
Console.WriteLine("Base");
}
public void Test2()
{
Console.WriteLine("Base");
}
}
private class Derived : Base
{
public override void Test()
{
Console.WriteLine("Derived");
}
public void Test2()
{
Console.WriteLine("Derived");
}
}
static void Main()
{
Base b = new Base();
Derived d = new Derived();
Base dInB = new Derived();
b.Test();
d.Test();
dInB.Test();
b.Test2();
d.Test2();
dInB.Test2();
Console.ReadKey(true);
}
输出:
Base // Base.Test()
Derived // Derived.Test()
Derived // Derived.Test()
Base // Base.Test2()
Derived // Derived.Test2()
Base // You think you're calling Derived.Test2(), but you actually call Base.Test2()
实际上此示例无效,因为它应该使用Derived类中new
中的public new void Test2()
关键字。
它就像运算符重载一样工作。它实际上并没有覆盖任何东西。如果您具有确切类型Derived
,则会调用新方法。
你必须非常小心隐藏成员,这完全不像重写(类)或实现(接口)。只有当您拥有 完全 类型时,才会调用 new
方法,否则仍然会调用基类型的方法!
答案 1 :(得分:3)
不同之处在于,在第一种情况下,你要覆盖,在第二种情况下,你隐藏的是完全不同的。
在第一种情况下:
class B: A
{
void Foo()
{
B b = new B();
A a = b;
a.GetData() //B's GetData() will be called
b.GetData() //B's GetData() will be called
}
}
另一方面,在第二种情况下:
class B: A
{
void Foo()
{
B b = new B();
A a = b;
a.GetData() //A's GetData() will be called
b.GetData() //B's GetData() will be called
}
}
在第二种情况下,您只是隐藏A的GetData()实现,但即使变量引用类型B的实例,您也始终能够通过变量类型A调用A的实现。请注意,这是完全不同的从最重要的行为来看。
答案 2 :(得分:0)
public class A
{
public virtual string GetData() { return "A";}
}
public class B : A
{
public override string GetData() { return "B"; }
}
如果您使用以下代码块中的类,您会期望什么?
A a = new A();
B b = new B();
A c = new B();
Console.WriteLine(a.GetData());
Console.WriteLine(b.GetData());
Console.WriteLine(c.GetData());
这将打印“A”“B”“B”。变量c存储为A类型,但在执行该方法时,代码被解析为“真实”实现。 (请参阅谷歌的虚拟功能表和解决原则)
如果您不使用下面的代码中的虚拟和覆盖,则会打印“A”“B”“A”。
public class A
{
public string GetData() { return "A";}
}
public class B : A
{
public new string GetData() { return "B"; }
}