转:C#中的abstract与virtual
【abstract】
abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。
在类声明中使用 abstract 修饰符以指示类只能是其他类的基类。
抽象类具有以下特性:
·抽象类不能实例化。
·抽象类可以包含抽象方法和抽象访问器。
·不能用 sealed 修饰符修改抽象类,这意味着该类不能被继承。
·从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。
·在方法或属性声明中使用 abstract 修饰符以指示此方法或属性不包含实现。
抽象方法具有以下特性:
·抽象方法是隐式的 virtual 方法。
·只允许在抽象类中使用抽象方法声明。
·因为抽象方法声明不提供实实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。例如: public abstract void MyMethod();
·实现由 overriding 方法提供,它是非抽象类的成员。
·在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
·在静态属性上使用 abstract 修饰符是错误的。
·在派生类中,通过包括使用 override 修饰符的属性声明可以重写抽象的继承属性。
【virtual】
virtual 关键字用于修改方法或属性的声明,在这种情况下,方法或属性被称作虚拟成员。虚拟成员的实现可由派生类中的重写成员更改。
调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。
默认情况下,方法是非虚拟的。不能重写非虚方法。
不能将 virtual 修饰符与以下修饰符一起使用:
static abstract override
除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。
·在静态属性上使用 virtual 修饰符是错误的。
·通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。
【override】 (覆盖上面两种关键字修饰方法)
使用 override 修饰符来修改方法、属性、索引器或事件。重写方法提供从基类继承的成员的新实现。由重写声明重写的方法称为重写基方法。重写基方法必须与重写方法具有相同的签名。
不能重写非虚方法或静态方法。重写基方法必须是虚拟的、抽象的或重写的。
重写声明不能更改虚方法的可访问性。重写方法和虚方法必须具有相同的访问级修饰符。
不能使用下列修饰符修改重写方法:
new static virtual abstract
重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且重写属性必须是虚拟的、抽象的或重写的。
using System;
namespace VitualMethod
{
class BeiseClass
{
public void RealMethod()
{
Console.WriteLine(@"The ""RealMethod"" method of ""BeiseClass"" class!");
}
public virtual void ViutualMethod()
{
Console.WriteLine(@"The ""ViutualMethod"" method of ""BeiseClass""class!");
}
}
class NewAndOverride: BeiseClass
{
/// <summary>
/// “new”用于隐藏基类成员的继承成员,是重写方法的另一种办法;
/// 在同一成员上同时使用 new 和 override 是错误的;
/// “override”是覆盖了虚拟方法。
/// </summary>
new public void RealMethod()
{
Console.WriteLine(@"The ""RealMethod"" method of ""NewAndOverride"" class!");
}
public override void ViutualMethod()
{
Console.WriteLine(@"The ""ViutualMethod"" method of ""NewAndOverride""class!");
}
}
class Tester
{
/// <summary>
/// 运行结果:
/// The "RealMethod" method of "BeiseClass" class!
/// The "RealMethod" method of "NewAndOverride" class!
/// The "ViutualMethod" method of "BeiseClass"class!
/// The "ViutualMethod" method of "NewAndOverride"class!
///
/// The "RealMethod" method of "BeiseClass" class!
/// The "ViutualMethod" method of "NewAndOverride"class!
/// </summary>
static void Main()
{
BeiseClass beiseClass = new BeiseClass();
NewAndOverride newAndOverride = new NewAndOverride();
beiseClass.RealMethod();
newAndOverride.RealMethod();
beiseClass.ViutualMethod();
newAndOverride.ViutualMethod();
Console.WriteLine();
//
// 注意:可以看到隐藏(new)方法仍然存在,而被覆盖(override)的方法已经不存在了;
//
beiseClass = newAndOverride;
beiseClass.RealMethod();
beiseClass.ViutualMethod();
}
}
}
【new】
使用 new 修饰符显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。
类 成员声明中可以使用与一个被继承的成员相同的名称或签名来声明一个成员。发生这种情况时,就称该派生类成员隐藏了基类成员。隐藏一个继承的成员不算是错 误,但这确实会导致编译器发出警告。若要取消此警告,派生类成员的声明中可以包含一个 new 修饰符,表示派生成员是有意隐藏基成员的。
using System;
namespace TheNewKeyword
{
class NewTestClassBase
{
public void PrintNewKeyword()
{
Console.WriteLine(@"This is base class!");
}
}
class NewTestClass : NewTestClassBase
{
//// <summary>
/// 如果这样写:
/// override public void PrintNewKeyword()
///
/// 将产生编译错误:
/// “TheNewKeyword.NewTestClass.PrintNewKeyword()” :
/// 无法重写继承成员“TheNewKeyword.NewTestClassBase.PrintNewKeyword()”,
/// 因为它未标记为 virtual、abstract 或 override。
/// </summary>
new public void PrintNewKeyword()
{
Console.WriteLine(@"This is ""new"" keyword!");
}
}
//// <summary>
/// TheNewKeyword 测试“new”关键字。
/// </summary>
class TheNewKeyword
{
//// <summary>
/// 运行结果:
/// This is base class!
/// This is "new" keyword!
/// </summary
static void Main()
{
//
// TODO: 在此处添加代码以启动应用程序
//
NewTestClassBase newTestClassBase = new NewTestClassBase();
NewTestClass newTestClass = new NewTestClass();
newTestClassBase.PrintNewKeyword();
newTestClass.PrintNewKeyword();
}
}
}