[Programming IL]创建一个接口,How To Declare A Interface

引言:

大家都知道接口是定义了一组契约,但是你知道接口的存在形式吗? 你想更深一步了解接口吗? Follow me. :)

概念:

Interfaces define a contract that other types can implement. Interfaces can have
static fields and methods, but they shall not have instance fields or methods.  Interfaces can define virtual methods. 

- From Common Language Infrastructure (CLI) Partition II

"A named group of methods, locations, and other contracts that shall be imple
mented by any object type that supports the interface contract of the same name"    - From ECMA / ISO

接口定义了一个契约,并由继承他的类来实现。

  1. 可以有静态的字段和方法,但是实际上他们不应该有(只是一种能力,但是不应该使用)。
  2. 定义的实例方法都是Virtual的.
  3. 不存在内存布局,因为他没有自己的实现. 从而也不知道那个方法占用多少个字节.等等 (有待继续深究)

Q & A - 从问题展开探索

Q: 是否继承接口的类都必须有接口的实现呢?

A: 抽象类除外. (Abstract Class Excluded)

   1: public interface ITest
   2:     {
   3:         void Run();
   4:     }
   5:     
   6:     public abstract class MyTest : ITest
   7:     {
   8:         public abstract void Run();
   9:         
  10:     }

更进一步,为什么Abstract的方法也可以呢 ?

换个角度如果不是Abstract的方法自然是可以的,但是为什么Abstract也行呢?

区别在于一个有具体的实现,而另一个无。然而对于最后生成的元数据结构来说,对于每个方法都存在自己的签名,实例方法如此,Abstract的方法也如是,而对于Abstract的实现类来说必定存在Abstract方法的具体实现,于是乎,这样的实现也是可以并且也是有道理的,权当一种.Net面向对象的一种特征好了. :). BTW: 不知道其他的面向对象语言怎样约定的?

举个例子:

   1: ITest test = new DerivedClass(); // Derived lass --> Abstract Class --> ITest
   2:  
   3: test.Call();
方法\类型  执行顺序 -> Interface Abstract class Derived Class
实例::方法 ITest:: Call() AbstractInstance::Call() DerivedInstance::Call()

依此类推, 这样也是对的

   1: public class MyVirtualTest: ITest
   2:     {
   3:         public virtual void Run(){}
   4:     }

Q: 定义上写可以定义静态的字段和方法? 那么为什么编译会报错

   1: public interface ITest
   2:     {
   3:         static void Run();
   4:     }

错误: The modifier 'static' is not valid for this item

这样也不行

   1: public interface ITest
   2: {
   3:     static int Count = 5;
   4: }

错误: Interfaces cannot contain fields

这样的例子是在C#中运行的,我们用IL试一下

   1:  
   2: .class interface public abstract auto ansi Roger.Testing.ITest
   3: {
   4:   .method public hidebysig newslot abstract virtual 
   5:           instance void  Run() cil managed
   6:   {
   7:   } // end of method ITest::Run
   8:  
   9:   .field private static int32 id
  10:  
  11: } // end of class Roger.Testing.ITest

编译成功, 我们反编译一下:

image

那定义一个静态方法呢?

   1: .class interface public abstract auto ansi Roger.Testing.ITest
   2: {
   3:   .method public hidebysig newslot abstract virtual 
   4:           instance void  Run() cil managed
   5:   {
   6:   } // end of method ITest::Run
   7:  
   8:   .field private static int32 id
   9:  
  10:   .method public static void MyStaticFun() cil managed
  11:   {
  12:     ret
  13:   }
  14:  
  15: } // end of class Roger.Testing.ITest

编译成功后继续反编译:

image

题外话:我们都知道Java里接口是可以定义静态变量,我想这是不是.Net设计时的一种考量,在CLI基础上内建了支持,而后根据语言特性定制,而C#不支持接口定义静态变量与方法. :)

再扯偏一点, 既然接口可以定义静态变量和方法,这些方法和变量需要在实现这个接口的类中再实现一次吗?

   1:  
   2: .class public auto MyClass extends [mscorlib]::System.Object
   3:                implements Roger.Testing.ITest
   4: {
   5:     // Implement the override methods
   6: }

答案: 不需要

原因: static变量为这个interface的l类型拥有,不需要继续实现,此例即为: ITest.id

posted on 2008-09-19 00:09 xwang 阅读(...) 评论(...) 编辑 收藏

导航

统计