接口的使用
很多朋友在了解了接口后不知道怎么用,实际上要真正理解接口及抽象类的概念还要等到有一定的项目经验以后。无论是接口还是抽象类都是设计层的东西,一个人如果没有对项目的开发或软件架构有个大体的概念,很难明白抽象概念所包含的巨大威力。
虽然如此我们还是要简单介绍一下接口的用法。接口的使用基本上来说有两方面,一方面是你如何定义接口,另一方面是如何使用别人定义的接口。这两方面相辅相成,你明白了如何定义接口那么你也一定会使用别人定义的接口。相反,你会使用别人定义的接口,那么久而久之你也就学会定义自己的接口了。前面我们讲过了接口的定义,这里我们说说如何使用别人的接口。
假设我们现在看到一个接口,就是上面的开关接口:
public interface ISwitch
{
void On();
void Off();
}
假设有一个电视类不是你写的,你也没有看懂里面的代码(比如代码有几千行你没时间看),但你知道它实现了上面这个接口,那么现在你能不能控制这个电视类所生成的电视对象?能!至少你可以让它“开”,让它“关”,你可以使用开关接口来控制所有的电视对象。这也是现实生活中所有电器开关都类似,所有汽车驾驶设备都相似的原因。你会开电视你就会开洗衣机,你会开大巴车你就会开小轿车,这些都蕴藏着接口的原理。
我们再举一个FCL里面的例子。FCL是.NET框架的基本类库,我们实际上一直在使用它。不管怎么说它是微软公司给我们定义的一套类库,是别人定义的,如果你理解了接口,那么在使用FCL类库时将会很方便。比如我们知道数组继承并实现了System.Collections命名空间下的IEnumerator接口,那么我们就可以用此接口来操作数组元素:
int [] a=new int [] {1,2,3,4,5 };
System.Collections.IEnumerator it=a.GetEnumerator();
while(it.MoveNext())
{
Console.WriteLine(it.Current.ToString());
}
集合命名空间的东西非常重要,看懂一个接口肯定比看懂一个数组类的用法简单得多,所以使用接口可以有效简化操作、提高编程效率。当然数组元素的遍历有很多方法,不一定要使用这个接口,这里的例子只是用来说明接口的用法。
要结合实际去理解接口的概念,要从实际编码中体会接口的好处。这样才会掌握接口的使用,接口的使用属于编程技术的内功,代码写到一定程度和深度时你会豁然开朗,到时你的功力又增加一分。最后我们再举一个形象的例子帮助你理解接口。思考一个问题,有人把皇上的“圣旨”理解为接口对不对?对,因为圣旨刚好满足接口的特性,皇上只管定义描述接口、接旨人(子类实例)去实现接口。这是到目前为止我认为能够阐明接口概念的一个较好的例子,也许对你的理解会有帮助。
委托
日常生活中我们经常使用委托方法处理问题,我们可以委托律师打官司,可以委托保险代理人办理保险等等。仔细考虑一下不难理解委托就是“托付、授权、委派、指派……为代表”的意思。在C#中,委托技术可以让我们将一个方法委托给一个对象,此后这个对象便可全权代理这个方法的执行了,这一点和我们日常生活中委托的概念非常相似。
委托的概念
委托机制实际上是基于一种传统的技术——函数指针,如果你熟悉C语言函数指针的用法,那么委托对你来说简直就是小菜一碟。我们以前也提到过,程序运行时要先把自己加载到内存中,那么实际上程序中的任何元素在内存中都有一个地址,变量、类、方法等都会有一个地址,在C语言中我们可以通过地址操作这些元素。比如要操作一个方法(C语言中叫函数),我们只需找到这个方法的地址,然后从这个地址往下执行直到方法结束就可以了。也是因为这个原因,C语言中函数指针可以操作任何函数,一个函数指针数组可以保存一系列函数的地址,通过一个循环就可以一次性调用这些函数,其中方便性是显而易见的。C#是面向对象的语言,没有指针这种技术,也不能直接操作内存地址,那么C#中用什么方法来实现类似的功能呢?就是委托。
委托类型本质上就是一种类类型,在C#中我们像建立一个类一样建立一个委托类型。委托类型可以定义委托对象(或说委托变量),委托对象可以代表一个方法,这个方法可以是对象的实例方法也可以是类的静态方法。然后我们可以给委托对象指定一个方法,随后我们就可以使用该委托执行这个方法了。比如我们有一个叫MySayDelegate的委托,我们可以如下书写程序:
static void Main(string [] args)
{
Me me=new Me();
//创建一个委托对象,让其代表SayHello方法
MySayDeleage mySay=new MySayDeleage(me.SayHello);
//通过委托对象来执行它所代表的方法,此时执行的是me对象的SayHello方法
mySay();
}
从上面可以看出,委托需要代表的方法是在创建委托对象时由委托的构造方法传入的。可能你现在会问,这里的MySayDeleage是不是可以代表任何方法呢?非也,我们知道方法的形式千变万化,某种类型的委托只能代表某种类型的方法。委托具体能代表什么样子的方法跟委托类型的定义有关。下面是委托类型的定义语法:
[访问修饰符] delegate 返回值类型 委托类型名称(参数列表)
其中delegate是系统关键字,用于创建委托类型。仔细观察你会发现,在委托的定义中,如果去掉delegate关键字剩下的也就是定义一个方法的语法。也正是因为如此,委托类型创建后它能代表的方法的类型也就定义了。也就是说委托返回值类型和参数列表决定了委托能够代表的方法,委托对象只能代表如此返回值类型和如此参数列表的方法