先看override的情况:
public class A
{
public A()
{
Console.WriteLine('A');
}
public virtual void Fun()
{
Console.WriteLine("A.Fun()");
}
}
public class B : A
{
public B()
{
Console.WriteLine('B');
}
public override void Fun()
{
Console.WriteLine("B.Fun()");
}
}
声明B类型的对象:
B test = new B();
test.Fun();
输出结果是:
A
B
B.Fun()
该结果中,先输出A,在输出B,说明初始化的时候,先执行基类,再执行化子类的构造函数
声明A类型的对象:
A test = new B();
test.Fun();
运行结果:
A
B
B.Fun()
说明无论是父类型还是子类型的对象 ,当使用override时,父类的虚函数完全被子类的函数给“覆盖”了。
再来看new的情况:
public class A
{
public A()
{
Console.WriteLine('A');
}
public virtual void Fun()
{
Console.WriteLine("A.Fun()");
}
}
public class B : A
{
public B()
{
Console.WriteLine('B');
}
public new void Fun()
{
Console.WriteLine("B.Fun()");
}
}
声明B类型的对象:
B test = new B();
test.Fun();
输出结果是:
A
B
B.Fun() ----此时与override的效果相同
声明A类型的对象:
A test = new B();
test.Fun();
运行结果:
A
B
A.Fun() ----此时,与override的情况不一样了。。。
结论:
1.new声明的方法,当使用子类的类型来调用的时候,它会运行子类中的函数,当类型是基类的话 ,则使用基类的函数来执行,可以简单的记忆:
override--覆盖(父类的没了,始终是儿子),new--新的(父子共存)
PS:只有使用virtual定义基类中的函数,并使用override标记子类的函数,才可以达到多态类----始终调用子类的方法
2.子类中override父类的方法,父类的方法一定要是virtual,而在子类中new父类的方法,父类的方法不一定要是virtual
3.抽象类中的抽象方法,必须要被子类override,不能new
4.override可以与sealed关键词连用: sealed override void F(),而new不行。被sealed修饰过的方法,不能再被子类重写
再来一道复杂点的网上看到的面试题:
public class A
{
public virtual void Fun1(int i)
{
Console.WriteLine(i);
}
public void Fun2(A a)
{
a.Fun1(1);
Fun1(5);
}
}
public class B : A
{
public override void Fun1(int i)
{
base.Fun1(i + 1);
}
}
B b = new B();
A a = new A();
a.Fun2(b);
b.Fun2(a);
运行上面语句,执行结果是什么?
先分析a.Fun2(b):传入的参数是B类型的,因此a.Fun1(1)执行的是B类型对象的Fun1方法,运行结果是2
然后执行Fun1(5),由于运行的是A类型对象的Fun2方法,Fun1自然就是A中的Fun1,运行结果是5
再分析b.Fun2(a):传入的参数是A类型的,因此a.Fun1(1)执行的是A类型对象的Fun1方法,运行结果是1
然后运行Fun1(5),由于运行的是B类型对象的Fun2方法,此时的Fun1已经被B覆盖掉了,因此执行的是被覆盖后的方法,运行结果是6
那么如果把B类中的override改成new,情况会是什么样呢?
由于public void Fun2(A a)的参数类型始终是A类型(当传入B类型时,会转成A类型,相当于A a = new B()的效果),而用new不会覆盖父类的方法,因此结果是:
1
5
1
5
出处:http://maobisheng.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。