virtual 用在方法和属性声明上,派生类可重写基类的方法和属性,对调用哪个实际方法实现起决定作用的是该实例的运行时类型(即 派生类
),而不是该实例的编译时类型(即 基类
)。
using System;
class A
{
public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
public override void F() { Console.WriteLine("D.F"); }
}
class Test
{
static void Main() {
D d = new D();
A a = d;
B b = d;
C c = d;
a.F();
b.F();
c.F();
d.F();
}
}
class A
{
public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
public override void F() { Console.WriteLine("D.F"); }
}
class Test
{
static void Main() {
D d = new D();
A a = d;
B b = d;
C c = d;
a.F();
b.F();
c.F();
d.F();
}
}
abstract 用在类、方法、属性、索引器及事件上。
抽象类具有以下特性: (SDK)
- 抽象类不能实例化。
- 抽象类可以包含抽象方法和抽象访问器。
- 不能用 sealed 修饰符修改抽象类,这意味着该类不能被继承。
- 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。
当从抽象类派生非抽象类时,这些非抽象类必须具体实现所继承的所有抽象成员,从而重写那些抽象成员。在下面的示例中
abstract class A { public abstract void F(); } abstract class B: A { public void G() {} } class C: B { public override void F() { // actual implementation of F } }
抽象类 A
引入抽象方法 F
。类 B
引入另一个方法 G
,但由于它不提供 F
的实现,B
也必须声明为抽象类。类 C
重写 F
,并提供一个具体实现。由于 C
中没有了抽象成员,因此可以(但并非必须)将 C
声明为非抽象类。
抽象方法具有以下特性:
- 抽象方法是隐式的 virtual 方法。
- 只允许在抽象类中使用抽象方法声明。
- 因为抽象方法声明不提供实实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。例如:
public abstract void MyMethod();
- 实现由 overriding 方法提供,它是非抽象类的成员。
- 在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
在一个抽象方法声明中可以重写虚拟方法。这使一个抽象类可以强制从它的派生类重新实现该方法,并使该方法的原始实现不再可用。在下面的示例中
using System; class A { public virtual void F() { Console.WriteLine("A.F"); } } abstract class B: A { public abstract override void F(); } class C: B { public override void F() { Console.WriteLine("C.F"); } }
类 A
声明一个虚拟方法,类 B
用一个抽象方法重写此方法,而类 C
重写该抽象方法以提供它自己的实现。