C# 多态/重写
有人能解释一下这两个例子的区别吗 甲级C# 多态/重写,c#,.net,oop,inheritance,polymorphism,C#,.net,Oop,Inheritance,Polymorphism,有人能解释一下这两个例子的区别吗 甲级 受保护的虚拟字符串GetData() B类 private覆盖字符串GetData() 以及以下各项: 甲级 受保护的字符串GetData() B类 私有字符串GetData() 假设“B类”继承自“A类” 我一直认为,如果要重写某个方法,需要在超类中使用virtual,在子类中使用override,但是我尝试删除关键字,并且程序编译得很好。区别到底是什么,如果有的话?区别在于,在第一种情况下,您是覆盖的,而在第二种情况下,您是隐藏的,这是完全不同的 在第
受保护的虚拟字符串GetData()
B类
private覆盖字符串GetData()
以及以下各项:
甲级
受保护的字符串GetData()
B类
私有字符串GetData()
假设“B类”继承自“A类”
我一直认为,如果要重写某个方法,需要在超类中使用
virtual
,在子类中使用override
,但是我尝试删除关键字,并且程序编译得很好。区别到底是什么,如果有的话?区别在于,在第一种情况下,您是覆盖的,而在第二种情况下,您是隐藏的,这是完全不同的
在第一种情况下:
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()实现但您始终能够通过类型为A的变量调用A的实现,即使该变量引用类型为B的实例。请注意,这与重写的行为完全不同。您显示的第二个示例隐藏了父级的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()
实际上,这个示例是无效的,因为它应该在派生类中使用public new void Test2()
中的new
关键字
它就像操作符重载一样工作。它实际上并没有覆盖任何内容。当您拥有确切的类型派生的时,它将调用新方法
隐藏成员时必须非常小心,这与重写(类)或实现(接口)完全不同。只有当您拥有精确类型时,它才会调用一个新的
方法,否则它仍然会调用基类型的方法强>
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”“B”“A”
谢谢你的解释!你看到B.GetData()下面的曲线了吗?您是否在查看+错误列表中看到警告?很难忽略,当你知道自己在做什么时,使用new关键字。在第一个例子中,B的方法不能是私有的。它不会编译。
public class A
{
public string GetData() { return "A";}
}
public class B : A
{
public new string GetData() { return "B"; }
}