l Virtual 用于修饰类
定义:在C#中,类的虚拟不是通过关键字virtual来声明的,用abstract修饰的类称为抽象类。抽象类不能实例化,但可以声明它们的变量,这样可以实现多态性。抽象类可以包含三种函数,抽象函数、虚拟函数和普通函数。下面的例子说明了抽象类的作用,即通过将抽象父类赋值为子类来实现多态。
class Program
{
static void Main(string[] args)
{
A a = new B();
a.DoSomething();
a.DoAnotherThing();
a.notVirtualFunc();
Console.ReadKey();
}
}
public abstract class A
{
public virtual void DoSomething()
{
Console.WriteLine("I'm A!");
}
public void notVirtualFunc()
{
Console.WriteLine("I'm not Virtual Func A");
}
public abstract void DoAnotherThing();
}
public class B : A
{
public override void DoSomething()
{
Console.WriteLine("I'm B!");
}
new public void notVirtualFunc()
{
Console.WriteLine("I'm not virtual Func but B");
}
public override void DoAnotherThing()
{
Console.WriteLine("I'm B,I'm Doing Another thing");
}
}
如果抽象类未实现其抽象函数,即例子中class A未实现DoSomething函数,则继承类必须实现该抽象函数,否则编译器会报错。在抽象类中也可以包含非抽象成员函数,如例子中的notVirtualFunc。在子类中实现抽象父类的非抽象成员时,使用的关键字并不是override,而是new。打印结果为:
I’m B,I'm Doing Another thing
I‘m not Virtual Func A
如果将override替换为new,则会出现如下结果,这说明了override是覆盖了父类的函数,而new仅为子类实现了一个同名函数,这样就不是多态了。
I’m B,I'm Doing Another thing
I‘m not Virtual Func A
需要注意的是,子类必须实现抽象父类的纯虚函数,即抽象父类中没有函数体的函数,这些函数用abstract来修饰而不像C++中用virtual来修饰,如例子中,如果类B中没有函数DoAnotherThing的话编译器会报错。
l Virtual 用于修饰成员函数
Virtual修饰的函数可以出现在非抽象类或者抽象类中。下面的例子与上一章的例子相似。
class Program
{
static void Main(string[] args)
{
A a = new B();
a.DoSomething();
a.DoAnotherThing();
A a1 = new A();
a1.DoSomething();
a1.notVirtualFunc();
Console.ReadKey();
}
}
public class A
{
public virtual void DoSomething()
{
Console.WriteLine("I'm A!");
}
public void DoAnotherThing()
{
Console.WriteLine("This is A!");
}
}
public class B : A
{
public override void DoSomething()
{
Console.WriteLine("I'm B!");
}
new public void DoAnothingThing()
{
Console.WriteLine("This is B!");
}
}
这个例子与上一个例子很像,但是不同点在于这个例子中的父类是普通的类,所以它可以进行实例化,而得到的结果也基本与上一个例子相同。
I'm not Virtual Func A
I'm A!
I‘m not Virtual Func A
需要注意的是,仅在抽象类中可以使用纯虚函数,即abstract修饰的成员函数,而未使用virtual修饰的函数,也不可以用override来覆盖,只可以使用new来生成一个新的同名函数。
区分一下virtual和abstract,就是abstract修饰的是抽象的用于继承的类或者成员函数,而virtual修饰的是可用于覆盖父类的成员函数。
l 接口类
接口类可以理解为一种特殊的抽象类,对应C++中的纯虚类。在C#中,接口的成员不允许使用public、private等修饰符,强制定义为公共的;接口成员函数不能包含代码体,只能在继承接口的类中实现,并且非抽象类必须实现接口的所有成员函数,只有子抽象类的抽象函数才可以不实现接口的成员函数;接口的成员函数不能用virtual、abstract来定义。
class Program
{
static void Main(string[] args)
{
interfaceBase base1 = new B();
interface1 face1 = new B();
base1.interfaceFunc();
face1.interfaceFunc();
Console.ReadKey();
}
}
interface interfaceBase
{
void interfaceFunc();
}
interface interface1 : interfaceBase
{
new void interfaceFunc();
}
public class B : interface1
{
public void interfaceFunc()
{
Console.WriteLine("I'm B");
}
}
这个例子的结果如下:
I'm B