实例解析C /CLI中的接口和泛型

2008-02-23 05:35:02来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

接口

  某些时候,让不相关的类分享一组公有成员,以便产生相同的行为,是很有用的。一个最基本的方法可能是通过一个公共的基类来定义他们,但这种方法太受局限,因为他需要这些类通过继承而互相关联,另外,他们也许更有着各自的基类,且CLI类型只支持单一类继承。

  C /CLI提供了一种方法,可利用多个类实现一组通用的功能,这就是我们通称的"接口",而一个接口则是一组成员函数的声明。要注意,这些函数只是声明,没有定义,也就是说,一个接口定义了一个由抽象函数组成的类型--这些函数实际上是纯虚函数,且在适当的时候,这些函数由客户类来实现。一个接口可允许不相关的类用同一名称和类型,实现同一功能,而无须需要这些类分享公共基类。在例1中演示了怎样定义一个接口。

  例1:

using namespace System;
public interface class ICollection
{
 void Put(Object^ o); //隐式public abstract
 Object^ Get(); //隐式public abstract
};

  一个接口的定义看上去很像一个类,除了用interface取代了ref或value,任何的函数都没有函数体,且均隐式为public和abstract。按照通常的约定,一个接口名带有起始字母I,后再接一个大写字母。(接口类和接口结构是等价的。)和类相似,一个接口也能有public或private访问可见性。

  一个接口能有一个或多个"基接口",在这种情况下,他将继承这些接口中的任何抽象函数,例如,在例2中,接口I2显式继承自I1,而I3显式继承自I1和I2,并通过I2隐式继承自I1。

  例2:

interface class I1 { /* ... */ };
interface class I2 : I1 { /* ... */ };
interface class I3 : I1, I2 { /* ... */ };

  一个类可像从基类继承时那样,来实现一个接口,见例3。

  例3:

public ref class List : ICollection
{
 public:
  void Put(Object^ o)
  {
   // ...
  }
  Object^ Get()
  {
   // ...
  }
  // ...
};

  一个类能实现一个以上的接口,在这种情况下,必须使用逗号来分隔接口列表,顺序倒不是很重要。当然,一个类在实现一个或多个接口时,也能显式地带有一个基类,在这种情况下,基类通常(但不是必须)写在最前面。

  假如一个类实现了一个接口,但没有定义接口中任何的函数,这个类就必须声明为abstract。当然了,任何从抽象类继承而来的类也是抽象类,除非定义了之前的这些抽象函数。接口不提供多重继承,和此相比,一个CLI类也只能有一个基类,然而,接口却提供某种和多重类继承相似的功能,但概念和之完全不同,例如,一个类不能从接口中继承函数定义;接口继承体系是单独于类继承体系的--实现同一接口的类也许会、但也许不会通过类继承体系相互关联。

  例4演示了一个类:Queue,其和List无关联(但除了这个外,两者都是从Object继承而来的),两者都实现了同一接口。

  例4:

public ref class Queue : ICollection
{
 public:
  void Put(Object^ o)
  {
   // ...
  }
  Object^ Get()
  {
   // ...
  }
  // ...
};

  现在,可用他来编写处理参数为List或Queue的函数了,如例5。

  例5:

ref class Item { /* ... */ };
void ProcessCollection(ICollection^ c);
int main()
{
 List^ myList = gcnew List;
 Queue^ myQueue = gcnew Queue;
 ProcessCollection(myList);
 ProcessCollection(myQueue);
}
void ProcessCollection(ICollection^ c)
{
 Item^ x = gcnew Item();
 /*1*/ c->Put(x);
 /*2*/ x = static_cast<Item^>(c->Get());
}

  在标号1和2中,为访问底层的List或Queue,使用了一个指向接口的句柄c,由此,您可传递给ProcessCollection一个指向任意对象的句柄,只要他的类实现了这个接口,或他是从实现了这个接口的类继承而来的。

  例6演示了一个包含只读属性X、只写属性Y、读写属性Z的接口,对读写属性来说,get和set声明的顺序并不重要。

  例6:

public interface class IProperties
{
 property int X { int get(); }
 property String^ Y { void set(String^ value); }
 property Object^ Z { Object^ get(); void set(Object^ value); }
};

  一个接口的成员,能够为静态数据成员、实例或静态函数、静态构造函数、实例或静态属性、实例或静态事件、操作符函数、或任意的嵌套类型。

  一般来说,我们会用for each语句来枚举集合中的任何元素,要对集合中的每个元素逐个进行操作,可使用如下语法:

   for each (表达式形式的类型标识符)
    嵌入语句

  表达式类型必须为一个"集合类型",假如要成为一个集合类型,这个类型必须实现接口System::Collections::IEnumerable,如例7中所定义。

  例7:

public interface class IEnumerable
{
 IEnumerator^ GetEnumerator();
};

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: C Builder 可视化组件库(VCL)标准组件 二

下一篇: 在未来时态下研发C 程式