谈谈C#中的三个关键词new , virtual , override

荒废了一段时间之后.还是觉得写写博客能充实一些,而且也可以更好的记录自己的点滴,鞭策自己的学习,积累都是从一点一滴做起来的,所以,还是从小事做起.

这几天在网上,看到有兄弟讨论new , virtual , override 这三个关键词的区别,本身自己基础学的就不咋的,也趁这机会一点点的加强下.
想起一句话,积累都是从平时做起的.

费话少说,先看一下MSDN上对于这三个关键字的定义

使用 new 修饰符显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。


(按我的理解,就是一个基类.如果派生类中有和基类同名的方法时,要用new隐式声明,不然的话,是会有错误的.)
        
virtual 关键字用于修改方法或属性的声明,在这种情况下,方法或属性被称作虚拟成员。虚拟成员的实现可由派生类中的重写成员更改。
调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。默认情况下,方法是非虚拟的。不能重写非虚方法。
不能将 virtual 修饰符与以下修饰符一起使用:
static      abstract      override

        使用 override 修饰符来修改方法、属性、索引器或事件。重写方法提供从基类继承的成员的新实现。由重写声明重写的方法称为重写基方法。重写基方法必须与重写方法具有相同的签名。
不能重写非虚方法或静态方法。重写基方法必须是虚拟的、抽象的或重写的。
重写声明不能更改虚方法的可访问性。重写方法和虚方法必须具有相同的访问级修饰符。
不能使用下列修饰符修改重写方法:
new     static      virtual     abstract
重写属性声明必须指定与继承属性完全相同的


看了之后有点晕,不要紧,借助于代码理解一下.

BaseClass.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace newvirtualoverride
{
    
public class BaseClass
    
{

    
public BaseClass() { }

    
public   void Print()    

    
{     
    Console.WriteLine(
"BaseClassPrint");     
    }

    
    }

}


InheritClass.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace newvirtualoverride
{
    
class InheritClass : BaseClass
    
{

        
public InheritClass() : base() { }   
  
       
public new virtual void Print() 
        

            Console.WriteLine(
"InheritClassPrint"); 
        }

    }

}
注意在派生类的同名Print方法的声明中,是用public new virtual void print()来声明的,如果这里写成public void print(),就会出错.上面有说到.


最后是主程序Program:
namespace NewVirtualOverride
{
    class Program
      {
        static void Main(string[] args)
          {
            BaseClass baseclass = new BaseClass();
              baseclass.Print();
            InheritClass inheritClass = new InheritClass();
              inheritClass.Print();
            Console.ReadLine();
          }
      }
}
运行这个程序会得到如下的结果:
BaseClassPrint
InheritClassPrint


下面我们看看virtual 和 override的搭配使用方法。
把BaseClass.cs改变如下:public virtual void Print();
把InheritClass.cs改变如下:public override void Print();
运行程序,结果如下:
BaseClassPrint
InheritClassPrint
     虽然结果与用new修饰符差不多,,但是其中的含意可不同,new是继承类对基类方法的重写而在继承类中产生新的方法,这时基类方法和继承方法之间没有任何的关系了,可是override就不同了,它也是对基类中方法的重写,但此时只是继承类重写了一次基类的方法。可以参考下面的例子来加深理解。
将Program.cs改变如下:
BaseClass baseclass = new BaseClass();
baseclass.Print();
InheritClass inheritClass = new InheritClass();
inheritClass.Print();
BaseClass bc = new InheritClass();
bc.Print();
分别运行用new修饰和用virtual/override修饰的程序,其结果如下:
new修饰的结果
BaseClassPrint
InheritClassPrint
BaseClassPrint
virtual/override修饰的结果:
BaseClassPrint
InheritClassPrint
InheritClassPrint
 
 
从上面的结果可以看出,在用new修饰的情况下,虽然bc是用InheritClass创建的实例,但是bc.Print()打印的还是BaseClassPrint,因为此时BaseClass和InheritClass中的Print已经是互不相同没有关系的两个方法了,而在virtual/override修饰的情况下,bc调用的Print方法已经被其子类override了,所以就打印了InheritClassPrint。
    最后我们再说说关键词之间的搭配关系,上面已经给出了virtual和override不兼容的几个关键词,这里就不重复了。我要说的是new和virtual在声明函数时,其实可以一块使用。因为这个函数是新的,故与其它任何new函数一样,隐藏了具有相同原型的继承来的函数。因为这个函数也是虚拟的,所以可以在派生类中进一步复位义,这样就为这个虚拟函数建立了一个新的基级别。最后用GrandsonClass类来看看。
GrandsonClass.cs修改如下:
namespace NewVirtualOverride
{
    class GrandsonClass : InheritClass
      {
        public GrandsonClass():base()
          {
          }
        public override void Print()
          {
            Console.WriteLine("GrandsonClassPrint");
          }
      }
}
InheritClass.cs修改如下:
namespace NewVirtualOverride
{
    class InheritClass : BaseClass
      {
        public InheritClass():base()
          {
          }
        new public virtual void Print()
          {
            Console.WriteLine("InheritClassPrint");
          }
      }
}
BaseClass.cs修改如下:
namespace NewVirtualOverride
{
    class BaseClass
      {
        public BaseClass()
          {
          }
        public virtual void Print()
          {
            Console.WriteLine("BaseClassPrint");
          }
      }
}
Program.cs修改如下:
namespace NewVirtualOverride
{
    class Program
      {
        static void Main(string[] args)
          {
            BaseClass baseclass = new BaseClass();
              baseclass.Print();
            InheritClass inheritClass = new InheritClass();
              inheritClass.Print();
            BaseClass grandsonClass = new GrandsonClass();
              grandsonClass.Print();
            Console.ReadLine();
          }
      }
}
运行结果为:
BaseClassPrint
InheritClassPrint
BaseClassPrint

注意第三个结果为BaseClassPrint,因为GrandsonClass类是派生于inheritClass,又因为inheritClass声明的为        new public virtual void Print(),所以这个方法和基类BaseClass是两个独立的,互相不影响的.所以会调用BaseClass的Print方法.


如果还不清楚,再看一下如果改为下面,结果会如何.
 Console.Out.WriteLine("***************************");
            BaseClass bc1 = new InheritClass();
            bc1.Print();
            BaseClass bc2 = new GrandsonClass();
            bc2.Print();

如果InheritClass和GrandsonClass都声明为new virtual的话.这时候都输出BaseClassPrint,道理同上

如果InheritClass设为override,GrandsonClass声明为new virtual的话.这时候都输出InheritClassPrint.(第一个很好理解,因为InheritClass重写了基类,所以这里输出InheritClassPrint.第二个GrandsonClass这里声明为new virtual,我的理解是这样的.当 BaseClass bc2 = new GrandsonClass();
bc2.Print();因为GrandsonClass这里声明为new virtual所以它相对于InheritClassPrint的print方法,在这里是一个独立的方法,也就是和基类的方法是互相不影响的,所以会去调用它的基类,也就是InheritClassPrint中的print方法.)
如果InheritClass和GrandsonClass都声明为override,.这时候都输出InheritClassPrint,GrandsonClassPrint

如果InheritClass声明为new virtual,GrandsonClass声明为override,.这时候都输出BaseClassPrint,BaseClassPrint

c#是单继承,我的理解就是比如
        BaseClass bc2 = new GrandsonClass();
        bc2.Print();
        如果InheritClass为override,GrandsonClass为virtual,那么输出的为InheritClass
        如果InheritClass为virtual,GrandsonClass为override,那么输出的BaseClassPrint

先说这么多吧:)有什么不正确的地方,请大家指出.


posted on 2008-03-26 15:41  书生  阅读(299)  评论(1编辑  收藏  举报

导航