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 约束 用于在泛型声明中约束可能用作类型参数的参数的类型。
请参见

浙公网安备 33010602011771号