接口定义了一种契约,如IComparer<T>这个接口定义的契约就是,所有实现了该接口的类必须含有Comparer这个方法。然后我们可以这样来使用接口:
IComparer<int> comparer = new Int32Comparer();
int result = comparer.Compare(1,2);
我们还可以写一个AnotherInt32Comparer类实现IComparer<int>,使用方法是一样的:
IComparer<int> comparer = new AnotherInt32Comparer();
int result = comparer.Compare(1,2);
这时我们不必关注comparer的具体实现,只需关注它的接口类型。这就是所谓面向接口编程。
配合依赖注入容器,还可以在不修改代码的情况下更改comparer的实现,如:
IComparer<int> comparer = Int32ComparerFactory.Create();
int result = comparer.Compare(1,2);
在Create方法内部,通过配置文件得到要创建的类的名称,再通过反射进行实例化。这就是所谓反射工厂。
我这样来说吧,假如我写了一个软件,可以支持让所有人给我写插件。那么你写的插件肯定是在我发布之后才写的,那么我怎么知道你的插件里都是些什么呢?
而如果我定义一个接口比如
public interface IPlugin
{
void OpenWindow();
void CloseWindow();
}
那么你写插件的时候只要使用了我这个接口,我就可以加载你的程序集,并且通过反射得到你所有实现了这个接口的类。例如我可以这样做:
void LoadPlugins()
{
string pluginPath = “插件的目录”;
//加载所有插件的程序集合
string[] assemblies = Directory.GetFiles(pluginPath, "*.dll");
//遍历所有插件
foreach (string plugin in assemblies)
{
//加载当前的程序集
Assembly assembly = Assembly.LoadFrom(plugin);
//遍历当前的程序集内所有类型
foreach (Type type in assembly.GetExportedTypes())
{
//假如是类,且不是基类,且继承于我的IPlugin接口
if (type.IsClass && !type.IsAbstract && typeof(IPlugin).IsAssignableFrom(type))
{
// 注意,这里根本不用知道你的插件的类的名字之类的信息,就把它实例化了,并且转换为IPlugin类型的
IPlugin p = (IPlugin)Activator.CreateInstance(type);
// 因为你的类实现了我的接口,所以我知道你的类里一定有这两个方法,可以随意调用了。
p.OpenWindow();
p.CloseWindow();
}
}
}
}
理论性的东西相信网上一找一大堆,这里我就举这么一个例子吧,你看看自己理解理解。
接口主要是用来规范和定义方法的。
像你的例子,如果不继承IComparer接口, Compare方法名你定义是Compare, 到我开发时我定义为CompareMy, 别人开发时又定义一个其它的, 这不就乱了吗? 你继承一个接口, 就起到了规范, 结束大家必须遵守.