一、接口的定义
如上MSDN上对接口的定义,接口只包含方法、委托或事件的签名。这句话用更通俗点的解释便是,接口只是
负责完成定义的操作,而不去实现具体的细节。如下面的IPlayer接口,它是一个玩游戏的接口,里面只是定义了相
应的方法,而不带方法的具体实现,代码如下:
下面是定义
1/** <summary>
2/// 玩游戏接口
3/// </summary>
4public interface IPlayer
5{
6 /** <summary>
7 /// 获取玩家的名字
8 /// </summary>
9 /// <returns>玩家的名字</returns>
10 string GetName();
11
12 /** <summary>
13 /// 由Player决定出什么手势
14 /// </summary>
15 /// <returns>本接口定义的三个常量之一</returns>
16 string Show();
17}
以上就是一个典型的接口的定义。定义了一个名为IPlayer的接口,内部定义了两个方法GetName和
Show。除了在接口里定义方法以外,我们还可以定义属性、索引及事件等,详细请查看MSDN上的定义或是
相关书籍,这里以属性为例简单介绍下,在接口里只能定义不实现,具体的实现是交给其子类去完成的,那么
属性应该怎么定义呢?
通常我们定义属性如下:
1/** <summary>
2/// 定义_Name属性,并提供get;set属性访问器
3/// </summary>
4private string _Name;
5public string Name
6{
7 get { return _Name; }
8 set { _Name = value; }
9}
那么在接口中又是怎么定义属性,并让其子类去实现呢?如下代码段:
1/** <summary>
2/// 定义接口,并在接口里定义一名为Name的属性
3/// </summary>
4public interface IAttribute
5{
6 string Name { get;set;}
7}
8/** <summary>
9/// 定义一个类去继承IAttribute接口,并实现其属性
10/// </summary>
11public class Component : IAttribute
12{
13 public string Name
14 {
15 get
16 {
17 return "张三";
18 }
19 set
20 {
21 this.Name = value;
22 }
23 }
24}
二、接口的实现
在本文开始部分曾经说过,接口只负责定义,不负责实现,具体的实现是交给他的子类去完成的。 OK,现在
我们就以上面定义的玩游戏的接口IPlayer为例,来简单的介绍下接口的实现。
就拿我的趣味编程中的玩剪刀石头布的案例来说吧,爷爷和奶奶从小就教授小孙子各中东西,其中玩趣味游戏
就他们常有的事,可小孙子还小不知道变换,每次都出剪刀,这样能赢他爷爷吗?有了这个分析,我们可以怎么做
呢?上面定义了接口,我们是不是直接去实现这个接口便OK了。爷爷和小孙子玩游戏,那么就定义两个类去继承
IPlayer接口。代码如下:
1/** <summary>
1/** <summary>
2/// 出手动作
3/// </summary>
4public class Options
5{
6 public static readonly string JIANDAO = "剪刀";
7 public static readonly string SHITOU = "石头";
8 public static readonly string BU = "布";
9}
游戏里只会出现这三种动作状态,所以我们可以进行封装,这里是通过类封装的,
爷爷(Grandpa)类和孙子(Grandson)类去实现接口(IPlayer)了。代码如下:1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace CallBack
6{
7 class Program
8 {
9 static void Main(string[] args)
10 {
11 //创建一个控制器对象,将提供给它的回调对象传入
12 Resolve resolve = new Resolve(new PlayBasketball());
13 resolve.Play();
14
15 resolve = new Resolve(new PlayFootball());
16 resolve.Play();
17 }
18 }
19
20 /** <summary>
21 /// 定义一个接口--回调对象
22 /// </summary>
23 public interface IPlayer
24 {
25 void Play();
26 }
27
28 /** <summary>
29 /// 篮球
30 /// </summary>
31 public class PlayBasketball:IPlayer
32 {
33 public void Play()
34 {
35 Console.WriteLine("玩篮球");
36 }
37 }
38
39 /** <summary>
40 /// 足球
41 /// </summary>
42 public class PlayFootball : IPlayer
43 {
44 public void Play()
45 {
46 Console.WriteLine("玩足球");
47 }
48 }
49
50 /** <summary>
51 /// 控制角色--控制器对象
52 /// </summary>
53 public class Resolve
54 {
55 //持有一个接口的引用,通过构造方法
初始化
56 private IPlayer player;
57 public Resolve(IPlayer player)
58 {
59 this.player = player;
60 }
61
62 public void Play()
63 {
64 player.Play();
65 }
66 }
67}
1/** <summary>
2/// 爷爷--玩家之一
3/// </summary>
4public class Grandpa:IPlayer
5{
6 public string GetName()
7 {
8 return "爷爷";
9 }
10
11 public string Show()
12 {
13 Random random = new Random();
14 int i = (int)(random.Next() * 1000) % 3;
15 switch (i)
16 {
17 case 0: return Options.JIANDAO;
18 case 1: return Options.SHITOU;
19 default: return Options.BU;
20 }
21 }
22}
1/** <summary>
2/// 孙子--玩家之一
3/// </summary>
4public class Grandson:IPlayer
5{
6 public string GetName()
7 {
8 return "孙子";
9 }
10
11 public string Show()
12 {
13 return Options.JIANDAO;
14 }
15}
如上,我们的GrandPa和GrandSon就实现了接口IPlayer,如下图示:
三、接口的继承
1interface IA { }
2interface IB:IA { }
3interface IC : IA, IB { }
4interface ID : IA, IB, IC { }
四、接口的特性
接口除了可以包含方法之外,还可以包含属性、索引器、事件等,而且这些成员都被定义为公有的。除此
之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类可以直接继承多
个接口,但只能直接继承一个类(包括抽象类)。
从类型上来说接口是引用类型的,类似于类,和抽象类的相似之处有三点:
1、不能实例化;
2、包含未实现的方法声明;
3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);
五、接口与回调
通常情况下,我们创建一个对象,并马上直接去使用它的方法。然而,在有些情况下,希望能在某个场景出现
后或条件满足时才调用此对象的方法。回调就可以解决这个“延迟调用对象方法”的问题。这个被调用方法的对象
称为回调对象。
首先创建一个回调对象,然后再创建一个控制器对象,将回调对象需要被调用的方法告诉控制器对象.控制器对象
负责检查某个场景是否出现或某个条件是否满足.当此场景出现或此条件满足时,自动调用回调对象的方法.示意性代
码如下: