c#virtual,override,new 关键字

C#中的Virtual、Override和new关键词 [日期:03-01] [字体:大 中 小] 

摘要:C#是继C++和Java语言后的又一面向对象的语言,在语法结构,C#有很多地方和C++及Java相似,但是又不同于它们,其中一些关键特别需要引起我们的注意。

virtual 关键字用于修改方法或属性的声明,在这种情况下,方法或属性被称作虚拟成员。虚拟成员的实现可由派生类中的重写成员更改。

调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。

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

不能将 virtual 修饰符与以下修饰符一起使用:

static   abstract   override

除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。

在静态属性上使用 virtual 修饰符是错误的。 通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。 上边是微软的官方说明,个人认为,如果自己觉得这个方法通用性不强就用virtual去声明这个方法,然后用户可以根据自己不同的情况首先继承它然后对它进行重载。下面我们来看一下微软给的例子:

    示例

在该示例中,Dimensions 类包含 x 和 y 两个坐标和 Area() 虚方法。不同的形状类,如 Circle、Cylinder 和 Sphere 继承 Dimensions 类,并为每个图形计算表面积。每个派生类都有各自的 Area() 重写实现。根据与此方法关联的对象,通过调用正确的 Area() 实现,该程序为每个图形计算并显示正确的面积。

 1 // cs_virtual_keyword.cs  2 // Virtual and override  3 using System;  4 class TestClass  5 {  6    public class Dimensions  7     {  8       public const double pi = Math.PI;  9       protected double x, y; 10       public Dimensions() 11        { 12       } 13       public Dimensions (double x, double y) 14        { 15          this.x = x; 16          this.y = y; 17       } 18 19       public virtual double Area() 20        { 21          return x*y; 22       } 23    } 24 25    public class Circle: Dimensions 26     { 27       public Circle(double r): base(r, 0) 28        { 29       } 30 31       public override double Area() 32        { 33          return pi * x * x; 34       } 35    } 36 37    class Sphere: Dimensions 38     { 39       public Sphere(double r): base(r, 0) 40        { 41       } 42 43       public override double Area() 44        { 45          return 4 * pi * x * x; 46       } 47    } 48 49    class Cylinder: Dimensions 50     { 51       public Cylinder(double r, double h): base(r, h) 52        { 53       } 54 55       public override double Area() 56        { 57          return 2*pi*x*x + 2*pi*x*y; 58       } 59    } 60 61    public static void Main()  62     { 63       double r = 3.0, h = 5.0; 64       Dimensions c = new Circle(r); 65       Dimensions s = new Sphere(r); 66       Dimensions l = new Cylinder(r, h); 67       // Display results: 68       Console.WriteLine("Area of Circle   = {0:F2}", c.Area()); 69       Console.WriteLine("Area of Sphere   = {0:F2}", s.Area()); 70       Console.WriteLine("Area of Cylinder = {0:F2}", l.Area()); 71    } 72 }

输出

Area of Circle   = 28.27

Area of Sphere   = 113.10

Area of Cylinder = 150.80

在前面的示例中,注意继承的类 Circle、Sphere 和 Cylinder 都使用了初始化基类的构造函数,例如:

public Cylinder(double r, double h): base(r, h) {}

其中关键字override表示派生类重写基虚方法,也可以使用关键字new,new表示隐藏基类中的虚方法。如果 override 关键字和 new 关键字均未指定,编译器将发出警告,并且派生类中的方法将隐藏基类中的方法。

下面我们通过微软的一个例子,来一下了解何时使用 Override 和 New 关键字。

首先声明三个类:一个名为 Car 的基类以及从该基类派生的两个类 ConvertibleCar 和 Minivan。基类包含一个可将有关汽车的描述发送到控制台的方法 (DescribeCar)。派生类方法也包含一个名为 DescribeCar 的方法,该方法显示派生类的独特属性。这些方法还调用基类的 DescribeCar 方法来演示从 Car 类继承属性的方式。

为了强调区别,ConvertibleCar 类使用 new 关键字来定义,而 Minivan 类使用 override 来定义。

      现在可以编写一些代码来声明这些类的实例,并调用它们的方法以便对象能够描述其自身:

正如预期的那样,输出类似如下所示:

Four wheels and an engine.

----------

Four wheels and an engine.

A roof that opens up.

----------

Four wheels and an engine.

Carries seven people.

----------

但是,在该代码接下来的一节中,我们声明了一个从 Car 基类派生的对象的数组。此数组能够存储 Car、ConvertibleCar 和 Minivan 对象。该数组的声明类似如下所示:

    

     然后可以使用一个 foreach 循环来访问该数组中包含的每个 Car 对象,并调用 DescribeCar 方法,如下所示:

此循环的输出如下所示:

Car object: YourApplication.Car

Four wheels and an engine.

----------

Car object: YourApplication.ConvertibleCar

Four wheels and an engine.

----------

Car object: YourApplication.Minivan

Four wheels and an engine.

Carries seven people.

----------

注意,ConvertibleCar 说明与您的预期不同。由于使用了 new 关键字来定义此方法,所调用的不是派生类方法,而是基类方法。Minivan 对象正确地调用重写方法,并产生预期的结果。

若要强制一个规则,要求从 Car 派生的所有类都必须实现 DescribeCar 方法,则应创建一个新的基类,将方法 DescribeCar 定义为 abstract。抽象方法不包含任何代码,仅包含方法签名。从此基类派生的任何类都必须提供 DescribeCar 的实现

 

virtual(C# 参考) Visual Studio 2005其他版本 Visual Studio 2010 Visual Studio 2008

virtual 关键字用于修饰方法、属性、索引器或事件声明,并且允许在派生类中重写这些对象。例如,此方法可被任何继承它的类重写。

复制public virtual double Area() {     return x * y; } 虚拟成员的实现可由派生类中的重写成员更改。有关使用 virtual 关键字的更多信息,请参见使用 Override 和 New 关键字进行版本控制(C# 编程指南) 和了解何时使用 Override 和 New 关键字(C# 编程指南)。

备注 --------------------------------------------------------------------------------

调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。

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

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

除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。

在静态属性上使用 virtual 修饰符是错误的。

通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。

示例 --------------------------------------------------------------------------------

在该示例中,Dimensions 类包含 x 和 y 两个坐标和 Area() 虚方法。不同的形状类,如 Circle、Cylinder 和 Sphere 继承 Dimensions 类,并为每个图形计算表面积。每个派生类都有各自的 Area() 重写实现。根据与此方法关联的对象,通过调用正确的 Area() 实现,该程序为每个图形计算并显示正确的面积。

在前面的示例中,注意继承的类 Circle、Sphere 和 Cylinder 都使用了初始化基类的构造函数,例如:

复制public Cylinder(double r, double h): base(r, h) {} 这类似于 C++ 的初始化列表。

复制// cs_virtual_keyword.cs using System; class TestClass {     public class Dimensions     {         public const double PI = Math.PI;         protected double x, y;         public Dimensions()         {         }         public Dimensions(double x, double y)         {             this.x = x;             this.y = y;         }

        public virtual double Area()         {             return x * y;         }     }

    public class Circle : Dimensions     {         public Circle(double r) : base(r, 0)         {         }

        public override double Area()         {             return PI * x * x;         }     }

    class Sphere : Dimensions     {         public Sphere(double r) : base(r, 0)         {         }

        public override double Area()         {             return 4 * PI * x * x;         }     }

    class Cylinder : Dimensions     {         public Cylinder(double r, double h) : base(r, h)         {         }

        public override double Area()         {             return 2 * PI * x * x + 2 * PI * x * y;         }     }

    static void Main()     {         double r = 3.0, h = 5.0;         Dimensions c = new Circle(r);         Dimensions s = new Sphere(r);         Dimensions l = new Cylinder(r, h);         // Display results:         Console.WriteLine("Area of Circle   = {0:F2}", c.Area());         Console.WriteLine("Area of Sphere   = {0:F2}", s.Area());         Console.WriteLine("Area of Cylinder = {0:F2}", l.Area());     } } 输出 --------------------------------------------------------------------------------

Area of Circle   = 28.27 Area of Sphere   = 113.10 Area of Cylinder = 150.80C# 语言规范

 

 

new(C# 参考) Visual Studio 2005其他版本 Visual Studio 2010 Visual Studio 2008

在 C# 中,new 关键字可用作运算符、修饰符或约束。

new 运算符 用于创建对象和调用构造函数。

new 修饰符 用于向基类成员隐藏继承成员。

new 约束 用于在泛型声明中约束可能用作类型参数的参数的类型。

请参见

posted @ 2012-02-19 22:18  Lovey  阅读(419)  评论(0编辑  收藏  举报