C#中虚方法,抽象类(方法)和接口的区别

来源:互联网 发布:知乎世界大学排名机构 编辑:程序博客网 时间:2024/06/05 15:38

这三种都是和继承相关的,其中虚方法和普通方法差不多,虚方法(virtual)可以实例化调用,也可以被继承类重写(override)。它的作用是当实例类型从继承类转换为基类时,类中的方法仍然是继承类中的实现。如果不使用虚方法而使用普通方法隐藏基类方法,那么当实例类型转换时,就变成了基类的实现。


using System;class A{   public void F() { Console.WriteLine("A.F"); }   public virtual void G() { Console.WriteLine("A.G"); }}class B: A{   new public void F() { Console.WriteLine("B.F"); }   public override void G() { Console.WriteLine("B.G"); }}class Test{   static void Main() {      B b = new B();      A a = b;      a.F();      b.F();      a.G();      b.G();   }}

在该示例中,A 引入一个非虚拟方法 F 和一个虚拟方法 G。类 B 引入一个新的非虚拟方法 F,从而隐藏了继承的 F,并且还重写了继承的方法 G。此例产生输出:
A.F
B.F
B.G
B.G
请注意,语句 a.G() 实际调用的是 B.G 而不是 A.G。这是因为,对调用哪个实际方法实现起决定作用的是该实例的运行时类型(即 B),而不是该实例的编译时类型(即 A)。

由于一个类中声明的方法可以隐藏继承来的方法,因此同一个类中可以包含若干个具有相同签名的虚拟方法。这不会造成多义性问题,因为除派生程度最大的那个方法外,其他方法都被隐藏起来了。


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();   }}

C 类和 D 类均含有两个具有相同签名的虚拟方法:A 引入的虚拟方法和 C 引入的虚拟方法。但是,由 C 引入的方法隐藏了从 A 继承的方法。因此,D 中的重写声明所重写的是由 C 引入的方法,D 不可能重写由 A 引入的方法。此例产生输出:

B.F
B.F
D.F
D.F
请注意,通过访问 D 的实例(借助一个派生程度较小的类型,它的方法没有被隐藏起来),可以调用被隐藏的虚拟方法。
以上引自:http://blog.csdn.net/sofoo/article/details/165691

抽象类(抽象方法)和接口类似,继承类都需要实现它们声明的函数。
抽象方法声明使用,是必须被派生类覆写的方法,抽象类就是用来被继承的;可以看成是没有实现体的虚方法;如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其他一般方法;抽象类不能有实体的。

相同点:
(1) 都可以被继承
(2) 都不能被实例化
(3) 都可以包含方法声明
(4) 派生类必须实现未实现的方法

不同点:
(1) 抽象基类可以定义字段、属性、方法实现;接口只能定义属性、索引器、事件、和方法声明,不包含字段以及方法实现。
(2) 抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。
(3) 接口可以被多重实现,抽象类只能被单一继承
(4) 抽象类的成员可以具有访问级别,而接口的成员全部public级别
(5) 抽象的子类可以选择性实现其基类的抽象方法,而接口的子类必须实现
(6) 接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法
(7) 接口可以用于支持回调,而继承并不具备这个特点
(8) 抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的
(9) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法

0 0
原创粉丝点击