C#
七、接口
7.1 接口概述
7.1.1 接口的特点
- 成员不允许有访问修饰符,所有成员默认为public
- 可以在接口中声明属性和方法,但不包含实现
- 声明属性时只需声明类型和读写
- 接口描述的是一种 “机制” 关系
7.1.2 接口和抽象类的区别
- 抽象类中声明的抽象方法在派生类中必须实现,而接口声明的方法也必须在派生类中实现
- 区别
- 从设计角度看
- 抽象类描述的一定是对象间共有的,派生类和抽象类之间是一种 “is-a” 的关系
- 接口描述的是一种 “can-do” 的关系,附加到对象上相当于某类型中部分实例的特性
- 而其中这部分实例都具有某种功能,这种功能不依托于类型,可能在多个类型之间都存在
- C#不支持多继承,所以使用接口
- 从设计角度看
7.2 接口实现
7.2.1 显式实现
- 特点
- 只能通过接口本身调用,即显式转型为接口
- 将机制关系与模型关系分开
- 不能有修饰符,如public、virtual、override等,与接口关联,不被看做是类的成员
- 只能通过接口本身调用,即显式转型为接口
- 实现方式
- 成员名前面需要显式加上接口前缀
- string[] IListable.ColumnValues { get… set }
7.2.2 隐式实现
- 特点
- 可以直接通过实现类进行调用
- 看作是类的成员
- 必须是public
- 可根据是否允许派生类重写决定是否使用 virtual 修饰
- 可以直接通过实现类进行调用
- 实现方式
- 和普通类成员一致,不需要加接口前缀
- 也不需要加 override
7.2.3 显式接口实现与隐式接口实现的比较
- 显式实现
- 将机制关系与模型关系分离
- 调用时明确指出是使用模型关系还是使用机制关系
- 原则
- 不是核心功能,不常用,则使用显式实现
- 通过接口的成员名称来判断其在类中的用途会造成歧义的,使用显式实现
- 例如,在卡车类中实现 ITrace接口的 dump() 方法
- 只从方法名称来看,该方法可能的作用是废弃、丢弃
- 但其实是接口定义的备份
- 例如,在卡车类中实现 ITrace接口的 dump() 方法
- 名称会发生重复的,使用显式实现
- 显式实现不会作为成员名称
7.3 接口继承
- 派生接口的显式实现需要使用原始接口名称作为显式实现的前缀
- 可以在派生接口中再明确声明自己要实现的基接口的方法
- 提供更好的可读性
7.4 版本控制
- 当需要为接口添加新功能时,应考虑通过派生的方式生成具有新功能的派生接口
- 兼容旧接口