在开发C#的过程中,实现接口时发现有两个选项,如下图:
第一个是“隐式实现接口”
第二个是“显示实现接口”
1、先定义一个接口:
public Interface ICollect
{
string GetName();
}
2、定义一个类,实现上面的接口
public class Api:ICollect
{
/// <summary>
/// 隐式实现接口(我们默认的都是使用隐式的接口)
/// </summary>
public string GetName()
{
return name;
}
}
显式的实现接口方式:
public class Api:ICollect
{
/// <summary>
/// 显式实现接口
/// </summary>
public string ICollect.GetName()
{
return name;
}
}
两者区别:
- 隐式实现接口时,我们有两种方式调用实现接口的方法(GetName()),即:
ICollect api=new Api();
api.GetName();
和
Api api=new Api();
api.GetName();
- 显式实现接口时,我们只有一种方法来调用GetName(),即:
ICollect api=new Api();
api.GetName();
最终结论:
1. 隐式实现接口时,接口和类(实现接口的类)都可以访问类中的方法;
2. 显式实现接口时,只有通过接口来访问类中的方法;
显式优点:
隐藏了实现接口的类的实现代码
扩展知识:在项目开发时,为什么要先写接口,再写实现类?
分别定义接口和实现类是架构思想中的开闭原则(扩展开发,修改关闭)的体现,例如:
假如你这个注册刚开始是对国内用户开放,中国用户注册成功返回“注册成功”,随着业务扩展,需要海外用户开放,假如美国用户返回“register success”,如果你有接口,可以在美国的AmericaUserServiceImpl.java中实现一个UserService.java的接口,来定义美国用户的注册业务,而不是在之UserServiceImpl.java中增加if else来对不同逻辑进行处理,这样,后续如果某个地区的注册业务有变动,只需要修改对应地区的实现类,修改不会影响到其他地区的实现类,降低了耦合性。
1、接口的意义在于 抽象、不拘细节,从而使同类事物在同一高度具有通用及可替代性。
2、在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务(即不是直接实例化在上层中),而是通过定义一组接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体类。
接口和抽象类有什么不同?
下面以C#语言为示例来讲,java也是类似的。
1 相同点
- 都可以被继承
- 都不能被实例化
- 都可以包含方法声明
- 派生类必须实现未实现的方法
2 区别
- 语法上
接口 | 抽象类 |
---|---|
接口只能定义属性、索引器、事件、和方法声明,没有普通成员变量 | 抽象类没有此限制 |
接口不能有构造方法(这简直是废话) | 抽象类可以有构造方法 |
接口中的所有方法必须都是抽象的 | 抽象类中可以包含非抽象的普通方法 |
接口中的方法只能是public类型的(默认) | 抽象类中的抽象方法的访问类型可以是public,protected |
接口可以用于支持回调 | 而继承并不具备这个特点 |
实现接口的类中的接口方法却默认为非虚的,(实现类的派生类,不可以再重写实现类接口方法,但派生类可以再显示实现接口的方法) 实现接口的类中的接口方法可以声明为virtual(这样实现类的派生类还可以重写该方法). | 抽象类实现的具体方法默认为虚的 |
- 其他方面
接口 | 抽象类 |
---|---|
接口是一个行为规范 | 抽象类是一个不完整的类,需要进一步细化 |
接口可以被多重实现 | 抽象类只能被单一继承 |
接口大多数是关系疏松但都实现某一功能的类中 | 抽象类更多的是定义在一系列紧密相关的类间 |
接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性 | 抽象类是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性 |