查看: 2783|回复: 1

[教程] Windows Store Apps 开发手札 - 4(接口)

[复制链接]
发表于 2013-1-6 14:42 | 显示全部楼层 |阅读模式 |IP属地北京
快御云安全
看到接口,我就情不自禁地想起了大二的时候,辅导员,也是我们的Java老师,在讲台上大讲特讲接口的广泛用途。是的,接口这个东西无时无刻不让我想起Java。
说实话我不喜欢Java,这东西总有种让我不能把一切尽在掌握的感觉。Java的“高级”特性让我们看不到内存里的东西,这在调试时是非常不方便的(对我来说)。我喜欢在调试时看着我要监视的内存块,然后内容一点点变化,成就感油然而生。当然,出现错误也能第一时间明白是肿么回事。
万幸(或者说是不幸?),C++也引入了接口这种特性。在让子类有更多可定制性的同时,也将C++变得更加多元化,复杂化。
C++/CX中的接口也是一个ref类,一个接口类(或接口结构)自身可继承(或需要)多个接口类、可重载其成员函数,也可具有类型参数。
新的接口类具有以下特性:
    1. 接口类(或结构)必须在命名空间内声明且可具有公共或私有可访问性。仅将公共接口发送到元数据。
    2. 接口的成员可以包括属性、方法和事件。
    3. 所有接口成员既是隐式公开的又是virtual的。
    4. 不允许字段和静态成员。
    5. 用作属性、方法参数或返回值的类型只能是 Windows 运行时类型;这包括基本类型和枚举类类型。

下面的例子示范了如何声明和实现接口:
-声明与实现-
  1. using namespace Platform;

  2. namespace InterfacesTest
  3. {
  4.     public enum class PlayState {Playing, Paused, Stopped, Forward, Reverse};

  5.     public ref struct MediaPlayerEventArgs sealed      
  6.     {
  7.         property PlayState oldState;
复制代码

一个接口可从一个或多个接口继承。但与 ref 类或 ref 结构不同,接口不声明继承的接口成员。如果接口 B 从接口 A 继承,而 ref 类 C 从 B 继承,则 C 必须同时实现 A 和 B。如下:
  1. public interface struct A { void DoSomething(); };
  2. public interface struct B : A { void DoSomethingMore();};

  3. public ref struct C sealed : B    // can not be derived
  4. {
  5.     virtual void DoSomething(){}
  6.     virtual void DoSomethingMore(){}
  7. };
复制代码

我们还可以使用普通虚拟属性(virtual property)实现接口属性,并可以在实现类中提供自定义 getter setter
  1. // 接上面MyMediaPlayer类,实现CurrentTitle属性
  2. virtual property Platform::String^ CurrentTitle
  3. {
  4.     Platform::String^ get() {return "Now playing: " + _title;}
  5.     void set(Platform::String^ t) {_title = t; }
  6. }
复制代码

而如果接口声明仅有 getter 或仅有 setter 的属性,则实现类应显式提供 getter setter
  1. public interface class IMediaPlayer
  2. {
  3.     //...
  4.     property Platform::String^ CurrentTitle
  5.     {
  6.         Platform::String^ get();
复制代码

-泛型接口-
泛型这个概念对于使用.Net编程的人来说,应该不陌生。它为使用c#语言编写面向对象程序增加了极大的效力和灵活性。通过使用泛型类型参数 T,在编写其他客户端代码时能够使用的单个类,而不致引入运行时强制转换或装箱操作的成本或风险。


在C++/CX中,我们使用generic关键字来表示参数化类型(parameteric type)。不支持在 C++/CX 中创建公共用户定义的泛型接口。但可以创建私有泛型接口。
在下面的例子中,我们可以知道如何创建泛型接口,并在私有ref类中实现它,然后在公共ref类中将该类当作私有成员。
  1. // 接上面,在InterfacesTest namespace中
  2. public ref class MediaFile sealed {};

  3. // generic interface
  4. generic <typename T>
  5. private interface class  IFileCollection
  6. {
  7.     property Windows::Foundation::Collections::IVector<T>^ Files;
  8.     Platform::String^  GetFileInfoAsString(T file);
  9. };

  10. // private ref class that implements the generic interface
  11. private ref class MediaFileCollection : IFileCollection<MediaFile^>
  12. {
  13. public:
  14.     virtual property Windows::Foundation::Collections::IVector<MediaFile^>^ Files;
  15.     virtual Platform::String^  GetFileInfoAsString(MediaFile^ file){return "";}
  16. };

  17. public interface class ILibraryClient
  18. {
  19.     bool FindTitle(Platform::String^ title);
  20.     //...
  21. };

  22. // public ref class who has the implemention class as a private member
  23. public ref class MediaPlayer sealed : public IMediaPlayer, public ILibraryClient
  24. {
  25. public:
  26.     //IMediaPlayer
  27.     virtual event OnStateChanged^ StateChanged;
  28.     virtual property Platform::String^ CurrentTitle;
  29.     virtual property PlayState CurrentState;
  30.     virtual void Play()
  31.     {
  32.         auto args = ref new MediaPlayerEventArgs();
复制代码

可以看到,在MediaFileCollection类中,传入了MediaFile^当作参数类型。任何一个实现IFileCollectionref类都可以传入自己独特的ref类当作参数类型。泛型的优点展露无遗。

泛型接口的注意事项(万金油,来自MSDN):
    1. 泛型接口必须遵循控制可访问性、成员、需要关系、基类等内容的标准接口规则。
    2. 泛型接口可以采用前面带有 typename class 的一个或多个泛型类型参数。不支持非类型参数。
    3. 类型参数可以是任何 Windows 运行时类型。即,类型参数可以是引用类型、值类型、接口类、委托、基本类型或公共枚举类。
    4. 封闭式泛型接口 是从泛型接口继承的接口,并对所有类型形参指定具体的类型实参。它可以在可使用非泛型私有接口的任意位置使用。
    5. 开放式泛型接口 是具有一个或多个尚未为其提供具体类型的类型参数的接口。它可以在可使用类型的任意位置使用,包括用作另一个泛型接口的类型参数。
    6. 可以只参数化整个接口,而不是单个方法。
    7. 不能约束类型参数。
    8. 封闭式泛型接口具有隐式生成的 UUID。用户不能指定 UUID。
    9. 在接口中,对当前接口的任何引用(在方法参数、返回值或属性中)都假定引用当前实例化。例如,IMyIntf 表示 IMyIntf<T>。
    10. 当方法参数的类型是类型参数时,该参数或变量的声明将使用类型参数的名称,而不带任何指针、本机引用或句柄声明符。换言之,绝不会写入“T^”。
    11. 模板化的 ref 类必须是私有的。它们可以实现泛型接口,并且可以将模板形参 T 传递给泛型实参 T。模板化 ref 类的每个实例化本身都是一个 ref 类。

以上是关于接口的文章。下篇文章让我们讲讲C++/CX相对C++来说,有哪些习惯了的东西从我们的视野中消失了。


我的个人博客:http://www.cy198706.com 转载的话,请告知。


发表于 2024-7-28 16:30 | 显示全部楼层 |IP属地山东
感谢楼主分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋联系我们

Copyright © 2005-2024 PCBeta. All rights reserved.

Powered by Discuz!  CDN加速及安全服务由「快御」提供

请勿发布违反中华人民共和国法律法规的言论,会员观点不代表远景论坛官方立场。

远景在线 ( 苏ICP备17027154号 )|远景论坛 |Win11论坛 |Win10论坛 |Win8论坛 |Win7论坛 |WP论坛 |Office论坛

GMT+8, 2024-12-12 18:22

快速回复 返回顶部 返回列表