所谓接口,就是契约,用于规定一种规则由大家遵守。所以,.NET中很多的接口都以able为命名后缀,例如INullable、ICloneable、IEnumerable、IComparable等,意指能够为空、能够克隆、能够枚举、能够对比,其实正是对契约的一种遵守寓意,只有实现了ICloneable接口的类型,才允许其实例对象被拷贝。以社会契约而言,只有司机,才能够驾驶,人们必须遵守这种约定,无照驾驶将被视为犯罪而不被允许,这是社会契约的表现。由此来理解接口,才是对面向接口编程及其精髓的把握,例如:
interface IDriveable
{
void Drive();
}
面向接口编程就意味着,在自定义类中想要有驾驶这种特性,就必须遵守这种契约,因此必须让自定义类实现IDriveable接口,从而才使其具有了“合法”的驾驶能力。例如:
public class BusDriver : IDriveable
{
public void Drive()
{
Console.WriteLine("有经验的司机可以驾驶公共汽车。");
}
}
没有实现IDriveable接口的类型,则不被允许具有Drive这一行为特性,所以接口是一组行为规范。例如要使用foreach语句迭代,其前提是操作类型必须实现IEnumerable接口,这也是一种契约。
实现接口还意味着,同样的方法对不同的对象表现为不同的行为。如果使司机具有驾驶拖拉机的能力,也必须实现IDriveable接口,并提供不同的行为方式,例如:
public class TractorDriver: IDriveable
{
public void Drive()
{
Console.WriteLine("拖拉机司机驾驶拖拉机。");
}
}
在面向对象世界里,接口是实现抽象机制的重要手段,通过接口实现可以部分的弥补继承和多态在纵向关系上的不足,具体的讨论可以参见1.4节“多态的艺术”和7.4节“面向抽象编程:接口和抽象类”。接口在抽象机制上,表现为基于接口的多态性,例如:
public static void Main()
{
IList<IDriveable> drivers = new List<IDriveable>();
drivers.Add(new BusDriver());
drivers.Add(new CarDriver());
drivers.Add(new TractorDriver());
foreach (IDriveable driver in drivers)
{
driver.Drive();
}
}