什么是接口
- 接口与class类似,但是它只为其成员提供了规格,而没有提供具体的实现
- 接口的成员都是隐式抽象的
- 一个class或者struct可以实现多个接口
接口的实现
- 接口的成员都是隐式public的,不可以声明访问修饰符
- 实现接口对它的所有成员进行public的实现:
对象与接口的转换
- 可以隐式的把一个对象转化成它实现的接口:
虽然Countdown是一个internal的class,但是可以通过把它的实例转化成IEnumerator接口来公共的访问它的成员。
接口的扩展
- 接口可以继承其它接口
- IRedoable继承了IUndoable的所有成员
显式的接口实现
- 实现多个接口的时候可能会造成成员签名的冲突。通过显式实现接口成员可以解决这个问题。
- 本例中,想要调用相应实现的接口方法,只能把其实例转化成相应的接口才行:
另一个显式实现接口成员的理由是故意隐藏那些对于类型来说不常用的成员。
virtual的实现接口成员
- 隐式实现的接口成员默认是sealed的。
- 如果想要进行重写的话,必须在基类中把成员标记为virtual或者abstract。
输出分别是 child parent parent 因为child里面写的方法相当于隐藏了子类的方法 所以接口最终调用的是父类的方法
Override 相当于覆盖了原来的方法
这三个都是输出 child
最后两个输出都是parent
virtual的实现接口成员
- 无论是转化为基类还是转化为接口来调用接口的成员,调用的都是子类的实现:
- 显示实现的接口成员不可以被标记为virtual,也不可以通过寻常的方式来重写,但是可以对其进行重新实现。
在子类中重新实现接口
- 子类可以重新实现父类已经实现的接口成员
- 重新实现会“劫持”成员的实现(通过转化为接口然后调用),无论在基类中该成员是否是virtual的。无论该成员是显式的还是隐式的实现(但最好还是显式实现的)
- 转化为接口后调用重新实现的成员,就是调用子类的实现
输出Child Parent 既然已经转换为接口了 接口的直接实现就是它的父类 所以输出parent
输出 Child child 实例是child
输出 Child child parent
在子类中重新实现接口
如果Textbox是隐式实现的Undo:
那么:
- 说明重新实现接口这种劫持只对转化为接口后的调用起作用,对转化为基类后的调用不起作用。
- 重新实现适用于重写显式实现的接口成员。
重新实现接口的替代方案
- 即使是显式实现的接口,接口的重新实现也可能有一些问题:
- 子类无法调用基类的方法
- 基类的开发人员没有预见到方法会被重新实现,并且可能不允许潜在的后果
- 最好的办法是设计一个无需重新实现的基类:
- 隐式实现成员的时候,按需标记virtual
- 显式实现成员的时候,可以这样做:
如果不想有子类,那么直接把class 给 sealed。
接口与装箱
- 把struct转化为接口会导致装箱
- 调用struct上隐式实现的成员不会导致装箱