C#virtual override new



在 C# 中,派生类可以包含与基类方法同名的方法。

  • 基类方法必须定义为 virtual

  • 如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在new 关键字一样执行操作。

  • 如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。

  • 如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。

  • 可以从派生类中使用 base 关键字调用基类方法。

  • override、virtual 和 new 关键字还可以用于属性、索引器和事件中。

默认情况下,C# 方法为非虚方法。如果某个方法被声明为虚方法,则继承该方法的任何类都可以实现它自己的版本。若要使方法成为虚方法,必须在基类的方法声明中使用 virtual 修饰符。然后,派生类可以使用override 关键字重写基虚方法,或使用 new 关键字隐藏基类中的虚方法。如果 override 关键字和 new关键字均未指定,编译器将发出警告,并且派生类中的方法将隐藏基类中的方法。







C# 关键字--virtual

 

    virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。虚拟成员的实现可由派生类中的重写成员更改,而非虚拟成员是无法由派生类进行重写的,这一点是与Java不同的。Java语言中,只要在派生类中定义了与父类具有相同签名的方法,那么父类的方法就被重写。C#语言中,必须使用virtual关键字进行修饰,否则在派生类中进行重写会导致编译器报错。
    虚方法或者虚属性并不等同于抽象方法、抽象属性抽象方法抽象属性无法直接调用,必须通过派生类进行实现之后才能调用;而虚方法虚属性是表示在派生类中有可能进行重写的,但是如果没有重写,那么将调用父类中的该虚方法和虚属性。调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。
    默认情况下,方法是非虚拟的,不能重写非虚方法(除非使用new关键字)virtual 修饰符不能与staticabstract、private 或 override 修饰符一起使用。除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。注意:
    在静态属性上使用 virtual 修饰符是错误的。
    通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。

虚拟方法
   
 若一个实例方法的声明中含有 virtual 修饰符,则称该方法为虚拟方法。若其中没有 virtual 修饰符,则称该方法为非虚拟方法。非虚拟方法的实现是不会变的:无论是在声明它的类的实例上调用该方法还是在派生类的实例上调用,实现都是相同的。与此相反,一个虚拟方法的实现可以由派生类取代。取代所继承的虚拟方法的实现的过程称为重写该方法。
    class A
    {
       public void F() { Console.WriteLine("A.F"); }
       public virtual void G() { Console.WriteLine("A.G"); }
    }
    class B: A
    {
       new public void F() { Console.WriteLine("B.F"); }
       public override void G() { Console.WriteLine("B.G"); }
    }
    class Test
    {
       static void Main() {
            B b = new B();
            A ab = b;//这里a的类型是B类对象
            A a = new A();
            a.F();  //打印A.F
            b.F();  //打印B.F
            ab.F(); //打印A.F
            a.G();  //打印B.G
            b.G();  //打印B.G
            ab.G(); //打印B.G

       }
    }

注意:从a.F()与ab.G()返回的结果可以看出,利用new和override关键字对方法进行重写是有区别的。
  1. 基类对象调用基类对应的方法,不管是否是虚拟方法。
  2. 派生类对象分两种情况
    ①引用声明为派生类变量:调用派生类的方法
    ②引用声明为基类变量:
            ■如果利用override重写,那么调用派生类中的重写之后的方法。
            ■如果利用new重写,那么调用基类方法。
   注意:上述原则对虚拟属性同样适用!





virtual  关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。

默认情况下,方法是非虚拟的。不能重写非虚方法。

virtual 修饰符不能与 staticabstract, private 或 override 修饰符一起使用。

 

Override:

override 方法提供从基类继承的成员的新实现。由 override 声明重写的方法称为重写基方法。重写的基方法必须与 override 方法具有相同的签名。

重写的基方法必须是vitural,override,abstract类型的 ,不能重写非虚方法或是静态方法

所以override不能与vitural,new,static同时使用

override 属性,声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是virtualabstract 或 override 的。(注意:这里是属性,不是字段,字段是不能被重写的

 

New:

用于创建对象和调用构造函数。

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

 

 

下面用代码来说明:

  1.  //By Alan Liao 2008-10-22
  2.     class Father
  3.     {
  4.         protected string firstname;
  5.         protected string lastname;
  6.       
  7.         public Father()
  8.         {
  9.         }
  10.         public Father(string firstname, string lastname)
  11.         {
  12.             this.firstname = firstname;
  13.             this.lastname = lastname;
  14.         }
  15.         public virtual void GetFullName()
  16.         {
  17.             Console.WriteLine("Father:{0}   {1}", firstname, lastname);
  18.         }
  19.     }
  20.     class Son : Father
  21.     {
  22.         public int age;
  23.          public Son() : base() { }
  24.         public Son(string firstname, string lastname,int age):base(firstname,lastname)  
  25.         {
  26.             this.age = age;
  27.         }
  28.         //public new void GetFullName()
  29.         public override void GetFullName()
  30.         {
  31.             Console.WriteLine("Son:{0}  {1}", firstname, lastname);
  32.         }
  33.     }
  34.     class Program
  35.     {
  36.         static void Main(string[] args)
  37.         {
  38.             Father father = new Father("Alan""Liao");
  39.             Father son1 = new Son("Little Alan ""Liao",20);
  40.             father.GetFullName();
  41.             son1.GetFullName();
  42.             Console.ReadLine();
  43.         }
  44.     }

 

本代码输出:

Father:Alan Liao

Son:Little Alan Liao

若将36行换成35行(即将Override换成New)

输出结果为:

(其实代码中的virtual,override 都可以去掉,可以编译,运行通过,但是会有Warnning,结果同下)

Father:Alan Liao

Father:Little Alan Liao

 

可见结果不一样。

Father a=new Son();
   如上声明对象的情况时,使用new声明的方法使用的仍是父类方法,而override声明的方法使用的是子类中的方法.

    其实,根本原因是对象a会优先调用子类中的方法,如果子类没有重写父类的方法,a 就调用父类中的方法
   override 说明的是虚方法,在子类中覆盖父类中的方法

   new则不是,new是给子类新增加了一个函数,可以说除了函数名字相同以外,它跟基类里面的这个同名函数没有任何关系。 相当于重新新建了一个方法,从而隐藏了父类方法.
  

 

 

其它:

在 C# 中,派生类可以包含与基类方法同名的方法。

  • 基类方法必须定义为 virtual

  • 如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在 new 关键字一样执行操作。

  • 如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。

  • 如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。

  • 可以从派生类中使用 base 关键字调用基类方法。

  • overridevirtual 和 new 关键字还可以用于属性、索引器和事件中。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值