接口
抽象类与抽象方法
接口和抽象类提供了一种将接口与实现分离的更加结构化的方法。
接口只允许 public 方法,如果不加访问修饰符的话,接口的方法不是 friendly 而是 public。
private abstract 被禁止了是有意义的,因为你不可能在 AbstractAccess 的任何子类中合法地定义它。
创建抽象类和抽象方法是有帮助的,因为它们使得类的抽象性很明确,并能告知用户和编译器使用意图。抽象类同时也是一种有用的重构工具,使用它们使得我们很容易地将沿着继承层级结构上移公共方法。
接口创建
接口只能决定方法名、参数列表和返回类型,但是无法确定方法体。接口只提供形式,通常来说没有实现,尽管在某些受限制的情况下可以有实现。
接口被用来建立类之间的协议
和类一样,需要在关键字 interface 前加上 public 关键字(但只是在接口名与文件名相同的情况下),否则接口只有包访问权限,只能在接口相同的包下才能使用它
接口同样可以包含属性,这些属性被隐式指明为 static* 和 final**。*
使用 implements* 关键字使一个类遵循某个特定接口(或一组接口),它表示:接口只是外形,现在我要说明它是如何工作的。除此之外,它看起来像继承。*
默认方法
关键字 default 允许在接口中提供方法实现——在 Java 8 之前被禁止。
增加默认方法的极具说服力的理由是它允许在不破坏已使用接口的代码的情况下,在接口中增加新的方法。默认方法有时也被称为守卫方法或虚拟扩展方法.
多继承
多继承意味着一个类可能从多个父类型中继承特征和特性。
Java 通过默认方法具有了某种多继承的特性。
因为接口中仍然不允许存在属性(只有静态属性,不适用),所以属性仍然只会来自单个基类或抽象类,也就是说,不会存在状态的多继承。
方法签名包括方法名和参数类型,编译器也是用它来区分方法。
返回类型不是方法签名的一部分,因此不能用来区分方法。为了解决这个问题,需要覆写冲突的方法
Java 8 允许在接口中添加静态方法
接口的工作方式使得我们不需要显式声明其中的方法为 public,它们自动就是 public 的。
抽象类和接口
特性 | 接口 | 抽象类 |
---|---|---|
组合 | 新类可以组合多个接口 | 只能继承单一抽象类 |
状态 | 不能包含属性(除了静态属性,不支持对象状态) | 可以包含属性,非抽象方法可能引用这些属性 |
默认方法 和 抽象方法 | 不需要在子类中实现默认方法。默认方法可以引用其他接口的方法 | 必须在子类中实现抽象方法 |
构造器 | 没有构造器 | 可以有构造器 |
可见性 | 隐式 public | 可以是 protected 或友元 |
抽象类仍然是一个类,在创建新类时只能继承它一个。而创建类的过程中可以实现多个接口。
有一条实际经验:尽可能地抽象。因此,更倾向使用接口而不是抽象类。只有当必要时才使用抽象类。除非必须使用,否则不要用接口和抽象类。大多数时候,普通类已经做得很好,如果不行的话,再移动到接口或抽象类中。
完全解耦
完全看不懂
多借口结合
如果创建不带任何方法定义或成员变量的基类,就选择接口而不是抽象类。事实上,如果知道某事物是一个基类,可以考虑用接口实现它。
通常来说,extends
只能用于单一类,但是在构建接口时可以引用多个基类接口。注意到,接口名之间用逗号分隔。
重载方法仅根据返回类型是区分不了的
当打算组合接口时,在不同的接口中使用相同的方法名通常会造成代码可读性的混乱,尽量避免这种情况。
接口适配
接口最吸引人的原因之一是相同的接口可以有多个实现。
小结
恰当的原则是优先使用类而不是接口。从类开始,如果使用接口的必要性变得很明确,那么就重构。接口是一个伟大的工具,但它们容易被滥用。