且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C#中的virtual,abstract,override和new关键字

更新时间:2022-05-11 01:17:38

C#中virtual,abstract,override用于方法重载,子类覆盖了父类的相同方法,父类中的实现不可能再被外面调用。
new的作用是投影(shadowing),子类隐藏了父类的相同方法,通过强制类型转换外面还可以调用父类的实现。

下面是重载的例子
Code:

点击(此处)折叠或打开

  1. class Parent
  2.     {
  3.         public virtual Parent foo()
  4.         {
  5.             System.Console.WriteLine("Parent.foo()");
  6.             return this;
  7.         }
  8.     }

  9.     class Child : Parent
  10.     {
  11.         public override Parent foo()
  12.         {
  13.             System.Console.WriteLine("Child.foo()");
  14.             return this;
  15.         }
  16.     }

Test:

点击(此处)折叠或打开

  1. class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             Child c =new Child();
  6.             c.foo();
  7.             ((Parent)c).foo();
  8.         }
  9.     }
Result:
Child.foo()
Child.foo()

下面是投影的例子
Code:

点击(此处)折叠或打开

  1. class Parent
  2.     {
  3.         public Parent foo()
  4.         {
  5.             System.Console.WriteLine("Parent.foo()");
  6.             return this;
  7.         }
  8.     }

  9.     class Child : Parent
  10.     {
  11.         public new Child foo()
  12.         {
  13.             System.Console.WriteLine("Child.foo()");
  14.             return this;
  15.         }
  16.     }

Test:

点击(此处)折叠或打开

  1. class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             Child c =new Child();
  6.             c.foo();
  7.             ((Parent)c).foo();
  8.         }
  9.     }
Result:
Child.foo()
Parent.foo()

重载的规则:
  1. 父类提供实现,则父类使用virtual关键字
  2. 父类不提供实现,则父类自身和相关方法使用abstract关键字,此时子类必须提供实现
  3. 子类重载需使用override关键字,如省略当作new(即投影)处理,并且编译器报编译警告
  4. 重载时子类方法不能改写返回值类型
  5. 子类中可以使用base关键字引用父类的实现

投影的规则:
  1. 父类必须提供实现(甚至可以有virtual关键字)
  2. 子类应该使用new关键字,如省略也当作new处理,但编译器报编译警告
  3. 投影时子类方法可以改写返回值类型
  4. 子类中可以使用base关键字引用父类的实现

除此以外还有一种接口投影的情况,通过接口投影可以新定义一个和接口定义同名同参但不同返回类型的函数。
比如:
Code:

点击(此处)折叠或打开

  1. interface MyInterface
  2.     {
  3.         Object foo();
  4.     }

  5.     class MyImp : MyInterface
  6.     {
  7.         Object MyInterface.foo()
  8.         {
  9.             System.Console.WriteLine("MyInterface.foo()");
  10.             return null;
  11.         }

  12.         public MyImp foo()
  13.         {
  14.             System.Console.WriteLine("foo()");
  15.             return null;
  16.         }
  17.     }

Test:

点击(此处)折叠或打开

  1. MyImp myImp = new MyImp();
  2.     myImp.foo();
  3.     ((MyInterface)myImp).foo();

Result:
foo()
MyInterface.foo()