C#浅析 virtual、abstract、interface、override\new
【虚方法】
virtual关键字用于在基类中修饰方法、属性、索引器或事件声明,并且允许在派生类中重写这些对象。
virtual的使用会有两种情况:
情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。
情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。
【抽象方法】
abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现,请务必将抽象方法放在抽象类中。
非抽象类的派生类必须全部实现父类的抽象方法和抽象访问器,使用override关键字来实现。
【接口】
接口用于描述一组类的公共方法/公共属性
接口中的方法没有具体实现,也就是没有方法体,必须由继承者去实现而且必须全部实现。
接口中的方法不需要修饰符,默认就是公有的
接口可以包含方法、属性、索引器、事件。不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员
【虚方法 VS 抽象方法】
虚方法和抽象方法都可以供派生类重写
1. 虚方法必须有实现部分,抽象方法没有提供实现部分,抽象方法是一种强制派生类覆盖的方法,否则派生类将不能被实例化;而虚方法提供了选择,可以覆盖可以不覆盖。
2. 抽象方法只能在抽象类中声明,虚方法不是。
【抽象 VS 接口】
抽象类和接口都不能实例化
抽象类可以包含非抽象方法,而接口只能包含抽象方法
一个类可以实现多接口,单继承
1 class Father 2 { 3 public void F() { Console.WriteLine("A.F"); } 4 public virtual void G() { Console.WriteLine("A.G"); } 5 } 6 class Son : Father 7 { 8 new public void F() { Console.WriteLine("B.F"); }//new 隐藏了父类中的方法,父类中的F方法还存在 9 public override void G() { Console.WriteLine("B.G"); }//override 重写了父类中的方法,父类中的G方法就不存在了 10 } 11 class override_new 12 { 13 static void Main() 14 { 15 Son b = new Son(); 16 Father a = b; 17 a.F();//通过父类声明的对象 调用隐藏方法,会调用父类中的 A.F 18 b.F();//通过子类声明的对象 调用隐藏方法,会调用子类中的 B.F 19 a.G();// B.G //若Son中是 new void G(),则结果为 A.G 20 b.G();//B.G 21 } 22 } //输出 A.F B.F B.G B.G
1 public class A 2 { 3 public virtual void Fun1(int i) 4 { 5 Console.WriteLine(i); 6 } 7 public void Fun2(A a) 8 { 9 a.Fun1(1); 10 Fun1(5); 11 } 12 } 13 public class B : A 14 { 15 public override void Fun1(int i) 16 { 17 base.Fun1(i + 1); 18 } 19 public static void Main() 20 { 21 B b = new B(); 22 A a = new A(); 23 a.Fun2(b);//b.Fun1(1) a.Fun1(5) //2 5 24 b.Fun2(a);//a.Fun1(1) b.Fun1(5)// 1 6 25 } 26 } //输出 2 5 1 6