`
pcajax
  • 浏览: 2162713 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多
谈谈C#中的三个关键词new , virtual , override

 

 

  C#支持单继承,说到继承就不得不说new,virtual和override这三个关键词,灵活正确的使用这三个关键词,可以使程序结构更加清晰,代码重用性更高。
   

      以下是msdn中对new,virtual和override的定义:
      使用 new 修饰符显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。
      virtual 关键字用于修改方法或属性的声明,在这种情况下,方法或属性被称作虚拟成员。虚拟成员的实现可由派生类中的重写成员更改。调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。默认情况下,方法是非虚拟的。不能重写非虚方法。
      不能将virtual 修饰符与以下修饰符一起使用:
      static    abstract    override
      使用 override 修饰符来修改方法、属性、索引器或事件。重写方法提供从基类继承的成员的新实现。由重写声明重写的方法称为重写基方法。重写基方法必须与重写方法具有相同的签名。不能重写非虚方法或静态方法。重写基方法必须是虚拟的、抽象的或重写的。
      重写声明不能更改虚方法的可访问性。重写方法和虚方法必须具有相同的访问级修饰符。
   
      不能使用下列修饰符修改重写方法:
      new   static    virtual   abstract
      重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且重写属性必须是虚拟的、抽象的或重写的。
      可以稍微归纳一下:
      1. 对于基类中说明为虚的方法则必须在派生类中new或者override(注:对于基类的虚方法,虽然你在派生类中即不new也不override,但系统还是会提示你添关键字。否则系统将视其为隐藏。我们的意思是一样的,但总觉得明明确确写上关键字还是好些)。
      2. 如果用基类指针指向派生类对象的方式,动态匹配的源动力是virtual,而new和override都会阻止这种向下寻求匹配的行为,所以要使虚函数的性质得已保持下去,就要隐藏基类的虚方法,即在派生类中隐藏基类虚方法时,同时加以virtual关键字,使在多层次继承中能够调用到对象自身的版本。
      3.在多层次继承中,三个关键字使用次序有限定,new没有使用前提,即不管是普通方法、虚方法还是重写了的方法。virtual的使用,在它的基类不能有函数签名相同的方法,否则系统将提示添加new,即隐藏基类中的方法。virtual一般只出现一次,除非要在子类中隐藏父类的虚方法。

      override的使用是为了重写基类虚方法。
     

  上面的描述都很抽象,对于初学者可能不好理解,下面我将用示例来说明这三个用法和区别:此程序在vs2005下调试通过。其中有三个类,分别

为基类BaseClass,继承类InheritClass和继承类的继承类GrandsonClass代码分别如下:

  

Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->//BaseClass.cs
namespace NewVirtualOverride
{
class BaseClass
{
public BaseClass()
{
}
public void Print()
{
Console.WriteLine(
"BaseClassPrint");
}
}
}
//InheritClass.cs
namespace NewVirtualOverride
{
class InheritClass : BaseClass
{
public InheritClass():base()
{
}
public void Print()
{
Console.WriteLine(
"InheritClassPrint");
}
}
}
//GrandsonClass.cs
namespace NewVirtualOverride
{
class GrandsonClass : InheritClass
{
public GrandsonClass():base()
{
}
public void Print()
{
Console.WriteLine(
"GrandsonClassPrint");
}
}
}
//最后是主程序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

 

 

其实细心的朋友在编译这个项目时,会发现出现了如下的警告提示:

 

Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->class InheritClass:BaseClass
{
public InheritClass():base()
{}

//New Virtual Override InheritClass.Print()隐藏了继承的成员
//New Virtual Override BaseClass.Print()。如果是刻意隐藏请使用new
public void Print()
{
Console.WriteLine(
"Hello");
}
}
   
     大致意思是说,基类和继承类中有相同名字的方法,请在继承类中使用new来重新定义方法。这里的微妙之处在于,无论我们是隐式地指定new方法,还是显式的指定,new方法都与基类中的方法无关,在名称、原型、返回类型和访问修饰符方面都无关。
     我们将程序中的Print()方法都变成new public void Print()后,上面的异常就不会发生了。再次运行程序,结果不变。new就是继承类使用与基类方法相同的名字对基类方法的重写。
     下面我们看看virtual 和 override的搭配使用方法。
     把BaseClass.cs改变如下:public virtual void Print();
     把InheritClass.cs改变如下:public override void Print();
     运行程序,结果如下:
     BaseClassPrint
     InheritClassPrint

 

     虽然结果与用new修饰符差不多,,但是其中的含意可不同,new是继承类对基类方法的重写而在继承类中产生新的方法,这时基类方法和继承方法之间没有任何的关系了,可是override就不同了,它也是对基类中方法的重写,但此时只是继承类重写了一次基类的方法。可以参考下面的例子来加深理解。

将Program.cs改变如下:

 


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->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类来看看。
Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->将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
    可见在InheritClass中使用了new以后,就意味着它与基类的同名方法为两个不同方法了,而它又是虚拟的,所以它的子类还可以继续继承BaseClass的Print()方法。
    将函数声明为virtual 与将它声明为new virtual是一样的,因为new仍然是默认的。所以下面的两句是相同的:
    public new virtual void Print(); public virtual void Print();
    那么new virtual的意义又在什么地方呢?在大型的层次结构中,这可能很有用,比如如下的System.Windows.Form类的继承关系Object->MarshalByRefObject->Component->Control->ScrollableControl->
ContainerControl。
    很容易想象出将一个派生的窗体集合作为窗体对待,而不是作为Object的情形。
再将Program.cs修改如下:
Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->namespace NewVirtualOverride
{
class Program
{
static void Main(string[] args)
{
BaseClass baseclass
= new BaseClass();
baseclass.Print();
InheritClass inheritClass
= new InheritClass();
inheritClass.Print();
BaseClass grandsonClass1
= new InheritClass();
grandsonClass1.Print();
InheritClass grandsonClass2
= new GrandsonClass();
grandsonClass2.Print();
Console.ReadLine();
}
}
}

 

运行结果为:
BaseClassPrint
InheritClassPrint
BaseClassPrint
GrandsonClassPrint
<script type="text/javascript"><!-- google_ad_client = "pub-6770445892601887"; /* 468x60, 创建于 09-11-19 */ google_ad_slot = "4437639877"; google_ad_width = 468; google_ad_height = 60; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
分享到:
评论

相关推荐

    new,override,virtual 示例

    在C#编程语言中,`new`、`override`和`virtual`是三个非常重要的关键字,它们用于控制类成员(主要是方法)的行为,涉及到多态性这一核心概念。接下来我们将详细探讨这三个关键字以及它们在实际编程中的应用。 1. `...

    深入理解C#中new、override、virtual关键字的区别

    在C#编程语言中,`new`、`override` 和 `virtual` 是三个与继承和多态性密切相关的关键字。理解它们的区别对于编写高效的面向对象代码至关重要。 首先,`new` 关键字主要用作修饰符,有以下作用: 1. 创建对象:`...

    override abstract virtual interface比较

    在 C# 编程语言中,override、abstract、virtual、interface 是四个关键字,它们之间存在着紧密的联系,我们经常会遇到 override、abstract、virtual 这三个关键字的使用,而 interface 则是一种特殊的抽象类。...

    new、abstract、virtual、override,sealed关键字区别和使用代码示例

    C# 中的 new、abstract、virtual、override、sealed 关键字的区别和使用代码示例 摘要:本资源旨在对 C# 中的 new、abstract、virtual、override、sealed 关键字进行详细的解释和比较,并提供实践代码示例,以帮助...

    c# override new base 关系

    在C#编程语言中,`override`、`new` 和 `base` 是三个关键字,它们在处理类继承和方法重写时起着至关重要的作用。理解这三个关键字的关系和用法对于编写可扩展和灵活的代码至关重要。 首先,我们来看 `override` ...

    了解何时使用 Override 和 New 关键字(C# 编程指南)

    本文将详细探讨 C# 中 `override` 和 `new` 关键字的区别及其应用场景。 #### 基础概念 - **Override**: 当一个派生类需要修改或扩展从基类继承的方法的行为时,可以使用 `override` 关键字。这要求基类的方法必须...

    new和override区别的小例子

    在编程语言中,尤其是面向对象的语言如C#,`new`和`override`是两个非常重要的关键字,它们在处理类的继承和多态性时起到关键作用。理解这两个关键字的区别对于编写灵活、可扩展的代码至关重要。 首先,我们来看`...

    图解C# new和override的区别.doc

    在C#编程语言中,`new`和`override`关键字在继承关系中扮演着不同的角色,它们用于处理派生类与基类之间的方法和属性。理解这两者的区别至关重要,因为它们直接影响代码的行为。 首先,我们来看看`new`关键字。`new...

    C#中new和override的区别个人总结

    在C#编程语言中,`new`和`override`关键字都是用来处理方法重写和隐藏的,但它们的行为和用途有所不同。以下是对这两个关键字详细解释的个人总结。 首先,`override`关键字用于重写基类中的虚方法(virtual methods...

    C#中Override关键字和New关键字的用法详解

    在C#编程语言中,Override和New关键字是用于处理继承关系中方法和属性重定义的重要概念,它们在处理多态性方面起到关键作用。这里我们将深入探讨这两种关键字的用法和区别。 首先,Override关键字用于明确表示派生...

    C#虚方法(Virtual)详解

    在C#编程语言中,虚方法(Virtual)是一种关键特性,允许子类重写父类的行为。虚方法的概念在于动态绑定,即在运行时根据对象的实际类型决定调用哪个方法,而不是在编译时就已经确定。这使得面向对象编程中的多态性...

    C#虚方法Virtual+详解 很详细的哦

    在C#编程语言中,虚方法(Virtual Methods)是一个重要的面向对象特性,它允许子类重写父类的方法实现,从而实现多态性。本文将深入探讨C#中的虚方法,包括其概念、语法、使用场景以及与非虚方法、抽象方法、接口等...

    New与Override重写的区别例子.txt

    在C#编程语言中,`new` 和 `override` 关键字被用于实现多态性。多态性是面向对象编程的一个重要特性,它允许子类继承父类的方法并根据自己的需求进行修改或扩展。然而,`new` 和 `override` 在使用时有着本质的区别...

    C#中new的用法及与override的区别分析

    C#中new的用法有三种: (1)new是运算符,用于创建对象和调用构造函数。如Class1=new Class1();也可以为值类型调用默认的构造函数如int a=new int();此时a=0. (2)new是修饰符,用于隐藏基类成员的继承成员。override...

    C#的New关键字的几种用法

    C#语言中的New关键字是一个多功能的关键字,它有多种用法,分别是new运算符、新修饰符和new约束。下面我们将详细介绍这三种用法。 New运算符 New运算符是C#语言中用于创建对象和调用构造函数的关键字。例如: ```...

    c#中new-的几种用法-经典案例-公司应聘 c#经典案例.doc

    在 C# 中,new 运算符和 new 修饰符是两个不同的概念。new 运算符用于创建对象和调用构造函数,而 new 修饰符用于隐藏基类成员的继承成员。了解这两个概念的用法和应用场景对于编写高效、灵活的 C# 代码非常重要。 ...

    C# new和override的区别分析

    在C#编程语言中,`new` 和 `override` 关键字在继承关系中用于处理方法和属性的行为,它们有着显著的区别。以下是这两个关键字的详细解释及其在代码中的应用。 `new` 关键字: 1. **运算符**:`new` 作为运算符时,...

    详解C#用new和override来实现抽象类的重写区别

    在C#编程语言中,`new`和`override`关键字都是用来处理方法重写和隐藏的,但它们之间存在着显著的区别。这篇文章将深入探讨这两种方式在实现抽象类重写时的具体差异。 首先,我们来看一下抽象类的实现。在C#中,...

Global site tag (gtag.js) - Google Analytics