12.2 声明和实现接口
先来定义两个接口,每个都仅定义了一个方法成员,如代码清单12-2所示。
代码清单12-2 接口的定义
interface ISample
{
void Method1();
}
interface ISample2
{
void Method2();
}
我们在上述代码中定义了两个接口:ISample和ISample2。在接口的定义中省略了访问修饰符,那么意味着它们当前的访问级别是internal,即只能被同程序集的类“看到”并实现,而在程序集外根本无法“看到”。大家注意到了,这两个接口名称分别为ISample和ISample2。说到这里,顺便介绍一下接口的命名规则。接口的命名一般使用名词或名词短语,或者描述行为的形容词,尽可能少用缩写,不要使用下划线字符,大小写采用Pascal风格,即首字母和后面的每个单词的首字母都大写,其他字母小写。大家可能注意到了接口名字前的前缀I,它表示这个类型是一个接口。下面是几个合乎规范的例子:
❑IComponent(描述性名词)
❑IUserService(名词短语)
❑IDisposable(形容词)
请注意,上述接口命名的规则只是一个推荐规则,并非标准,具体规则应以您所在单位或者组织的规定为准。
截至目前,我们已经定义了两个接口,下一步要学习如何实现一个接口。从一定意义上说,接口只是表示其所定义成员的一种存在性,它是一个契约。
实现一个接口的语法如图12-4所示。
图 12-4 类实现接口
接下来,我们对定义接口的几个关键部分进行说明,如表12-2所示。
我们继续举例说明,先定义两个类,分别实现接口ISample和ISample2,如代码清单12-3所示。
代码清单12-3 实现接口
1 class ClassOne:ISample
2{
3 public void Method1()
4{
5 System.Console.WriteLine("from ClassOne.Method1()");
6}
7
8 public void Method2()
9{
10 System.Console.WriteLine("from ClassOne.Method2()");
11}
12}
13
14 class ClassTwo:ISample
15{
16 public void Method1()
17{
18 System.Console.WriteLine("from ClassTwo.Method1()");
19}
20}
上述代码的实现接口如图12-5所示。
图 12-5 实现接口
关于代码清单12-3的说明如表12-3所示。
接下来,我们来看看如何调用这两个实现类,如代码清单12-4所示。
代码清单12-4 实例化接口的实现类
class ClassExample
{
public static void Main()
{
ISample sample1=new ClassOne();
ISample sample2=new ClassTwo();
sample1.Method1();
sample2.Method1();
}
}
这段代码的执行结果如下:
from ClassOne.Method1()
from ClassTwo.Method1()
在上述代码中,要特别关注的是声明了两个类型为ISample的变量sample1和sample2,它们分别使用ClassOne和ClassTwo类进行了初始化。这说明接口类型的变量可以指向任何实现了这个接口的类的实例,这样固然很好,可以灵活地指定某个实现类,而不需要改变依赖这个接口的代码。但这样一来就只能通过这些接口类型的引用调用接口的方法,如果想要调用某个实现类中的自定义的、不在接口中的方法,就需要把引用强制类型为合适的类型。下面通过一个例子进行说明。
在ClassOne类中添加一个Method2方法,该方法的定义并未出现在接口ISample中,因此它属于ClassOne类,通过ISample接口的引用将无法看到访问到它,必须将ISample接口的引用向下转型到ClassOne类型才能进行访问,如代码清单12-5所示。
代码清单12-5 通过向下转型调用接口实现类的专属方法示例
1 class ClassOne:ISample
2{
3 public void Method1()//定义于ISample接口中的方法
4{
5 System.Console.WriteLine("from ClassOne.Method1()");
6}
7
8 public void Method2()//专属于ClassOne类的方法
9{
10 System.Console.WriteLine("from ClassOne.Method2()");
11}
12}
13
14 class ClassTwo:ISample
15{
16 public void Method1()//定义于ISample接口中的方法
17{
18 System.Console.WriteLine("from ClassTwo.Method1()");
19}
20}
21
22 class ClassExample
23{
24 public static void Main()
25{
26 ISample sample1=new ClassOne();
27 ISample sample2=new ClassTwo();
28 sample1.Method1();
29 sample2.Method1();
30//将ISample类型的引用向下转型到ClassOne类型的引用
31 ClassOne clsOne=(ClassOne)sample1;
32 clsOne.Method2();
33}
34}