在面向对象编程中,有两种截然不同的继承方式:实现继承和接口继承。在实现继承时候,在Java中,所有函数默认都是virtual的,而在C#中所有函数并不默认为virtual的,但可以在基类中通过声明关键字virtual,就可以在其派生类中通过关键字override重写该函数。
重写后的virtual函数依旧是virtual函数。由于virtual只对类中的实例函数成员有意义,所以成员字段和静态函数都不能声明为virtual,也不能与override和abstract一起用。C#中可以设置virtual属性、索引器或事件。
无virtual和override关键字“重写”
这是所谓的无virtual和override的“重写”其实只是隐藏。如果签名后的函数在基类中都进行了声明,却没有用virtual和override关键字,例如:
class Program
{
static void Main(string[] args)
{
A a1 = new A(); a1.Print();
A a2 = new B(); a2.Print();
A a3 = new C(); a3.Print();
Console.Read();
}
}
class A
{
public void Print()
{
Console.WriteLine("A");
}
}
class B : A
{
public void Print()
{
Console.WriteLine("B");
}
}
class C : B
{
public void Print()
{
Console.WriteLine("C");
}
}
//打印结果 A
A
A
有virtual和override关键字“重写”
在派生类中添加关键字virtual和override,实现对基类的重写:
class Program
{
static void Main(string[] args)
{
A a1 = new A(); a1.Print();
A a2 = new B(); a2.Print();
A a3 = new C(); a3.Print();
Console.Read();
}
}
class A
{
public void Print()
{
Console.WriteLine("A");
}
}
class B : A
{
public override void Print()
{
Console.WriteLine("B");
}
}
class C : B
{
public void Print()
{
Console.WriteLine("C");
}
}
//报错
在类的定义中,申明时定义的类叫申明类,执行实例化时候定义的类叫实例类。
此时编译器具体的检查的流程如下
1、当调用函数时,系统会直接去检查申明类,看所调用的函数是否为虚函数;
2、如果不是,那么它就直接执行该函数。如果是virtual函数,则转去检查对象的实例类。
3.在实例类中,若有override的函数,则执行该函数,如果没有,则依次上溯,按照同样步骤对父类进行检查,知道找到第一个override了此函数的父类,然后执行该父类中的函数。(星梦《C#虚函数virtual详解收藏》)
class Program
{
static void Main(string[] args)
{
A a1 = new A(); a1.Print();
A a2 = new B(); a2.Print();
A a3 = new C(); a3.Print();
Console.Read();
}
}
class A
{
public virtual void Print()
{
Console.WriteLine("A");
}
}
class B : A
{
public override void Print()
{
Console.WriteLine("B");
}
}
class C : B
{
public void Print()
{
Console.WriteLine("C");
}
}
//打印结果 A
B
B
class Program
{
static void Main(string[] args)
{
A a1 = new A(); a1.Print();
A a2 = new B(); a2.Print();
A a3 = new C(); a3.Print();
Console.Read();
}
}
class A
{
public virtual void Print()
{
Console.WriteLine("A");
}
}
class B : A
{
public override void Print()
{
Console.WriteLine("B");
}
}
class C : B
{
public override void Print()
{
Console.WriteLine("C");
}
}
//打印结果 A
B
C