【所见即所得】抽象类、接口的一点费解

 

 

一、问题引入:

看一些开源项目源码的时候,经常看到如下的结构设计:

 

我表示很费解。

image

二、问题分析:

为了分析问题,我写了几个测试的类和接口,如下:

接口:

	public interface A
	{
        string Test1();

        void Test2();
	}

抽象类:

 public abstract  class B :A{
       #region A 成员

       public virtual string Test1() {
           Console.WriteLine("abstract B Test1");
           return "B Test1";
       }

       public virtual void Test2() {
           Console.WriteLine("abstract B Test2");
           
       }

       #endregion
   }

 

同时继承抽象类和实现接口的具体类:

public   class C :B,A{
    }

 

只继承抽象类的具体类:

 public  class D :B{
    }

 

 

测试也下各种用法:

             A a1 = new C();
                A a2 = new D();

                B b1 = new C();
                B b2 = new D();

                a1.Test1();
                a2.Test1();
                Console.WriteLine(a1.GetType().GetInterfaces()[0]);
                Console.WriteLine(a2.GetType().GetInterfaces()[0]);
                Console.WriteLine(a1.GetType().BaseType);
                Console.WriteLine(a2.GetType().BaseType);
                Console.WriteLine("-----------------------------------------------");
                Console.WriteLine(b1.GetType().GetInterfaces()[0]);
                Console.WriteLine(b2.GetType().GetInterfaces()[0]);
                Console.WriteLine(b1.GetType().BaseType);
                Console.WriteLine(b2.GetType().BaseType);

 

结果如下:

image

也就是这两个具体类从表面上(运行结果)看没有什么不同。

 

我仔细的查看了一下他们的IL代码:

.class public auto ansi beforefieldinit D
    extends FMS_Refacting.interfaceAndabsctract.B
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: call instance void FMS_Refacting.interfaceAndabsctract.B::.ctor()
        L_0006: ret 
    }

}

 

 

 

.class public auto ansi beforefieldinit C
    extends FMS_Refacting.interfaceAndabsctract.B
    

implements FMS_Refacting.interfaceAndabsctract.A

{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: call instance void FMS_Refacting.interfaceAndabsctract.B::.ctor()
        L_0006: ret 
    }

}

 

唯一的不同就是红色部分标出。但这不会影响什么,因为根据继承的定义,D是通过B来implements了A的,这种传递性和上面的没有什么区别。所以从这里看也没什么不同。

也就是说,这个两种形式是一样的!!!

 

我们知道:

接口:是包含一组虚方法的抽象类型,其中每一种方法都有其名称、参数和返回值。接口方法不能包含任何实现,CLR允许接口可以包含事件、属性、索引器、静态方法、静态字段、静态构造函数以及常数。但是注意:C#中不能包含任何静态成员。一个类可以实现多个接口,当一个类继承某个接口时,它不仅要实现该接口定义的所有方法,还要实现该接口从其他接口中继承的所有方法。

抽象类:提供多个派生类共享基类的公共定义,它既可以提供抽象方法,也可以提供非抽象方法。抽象类不能实例化,必须通过继承由派生类实现其抽象方法,因此对抽象类不能使用new关键字,也不能被密封。如果派生类没有实现所有的抽象方法,则该派生类也必须声明为抽象类。另外,实现抽象方法由override方法来实现。

 

抽象类和接口比起来,有一个好处,就是某些函数可以实现具体的方法,而并不一定是声明抽象的方法,而接口只能声明抽象方法(并且强制子类实现),所以用一个抽象类来实现某个接口可以实现一些通用的方法,而这些具体实现的方法里还可以调用抽象方法,所以减少了子类中的重复代码。

 

所以,D的继承形式我觉着是比较常用的,但是为什么又出现C继承形式了呢?我的猜想:

  • 1、应该是框架上的需要便于扩展?
  • 2、与设计模式有关?
  • 3、美观?

三、最后

我还是不能确定为什么要这么设计,有什么特殊的原因是我没有想到的么?如果你知道请告诉我,我也会一直的寻找原因。不胜感激。

posted on 2012-01-13 17:01  付之一笑  阅读(1907)  评论(18编辑  收藏  举报

导航