Java8允许在接口内声明静态方法;
Java8可以在接口内添加默认方法.
实现类会默认继承接口的默认方法,实现类可以重写该方法.
通过在Java8中引入这一新特性,,缺失的方法实现会作为接口的一 部分由实现类继承(所以命名为默认实现),而无需由实现类提供。
复习一下抽象类和抽象接口:
1.抽象类可以有实例变量(字段),接口不能有实例变量
2.一个类只可以继承一个抽象类,但是可以实现多个接口
9.3 默认方法的使用模式
默认方法的两种用例:可选方法和行为的多继承。
9.3.1 可选方法
采用默认方法之后,你可以为这种类型的方法提供一个默认的实现,这样实体类就无需在自己的实现中显 式地提供一个空方法。通过这种方式,你可以减少无效的模板代码。
9.3.2 行为的多继承
这里的多继承并不是类 意义上的继承,而是通过实现多个接口,自动继承多个接口中的默认方法,从而实现类似多继承的效果
关于继承的一些错误观点:
继承不应该成为你一谈到代码复用就试图倚靠的万精油。比如,从一个拥有100个方法及字段的类进 行继承就不是个好主意,因为这其实会引入不必要的复杂性。你完全可以使用代理有效地规避这种窘 境,即创建一个方法通过该类的成员变量直接调用该类的方法。这就是为什么有的时候我们发现有些 类被刻意地声明为final类型:声明为final的类不能被其他的类继承,避免发生这样的反模式,防 止核心代码的功能被污染。注意,有的时候声明为final的类都会有其不同的原因,比如,String 类被声明为final,因为我们不希望有人对这样的核心功能产生干扰。 这种思想同样也适用于使用默认方法的接口。通过精简的接口,你能获得最有效的组合,因为你可以 只选择你需要的实现。
9.4 解决冲突的规则
public interface Animal {
default void eat(){
System.out.println("所有的动物都会进食");
}
}
public interface SmallAnimal extends Animal{
default void eat(){
System.out.println("所有的小动物都会进食");
}
}
public class Cat implements Animal,SmallAnimal{
}
@Test
public void test01() {
new Cat().eat();
}
输出结果:所有的小动物都会进食
9.4.1 解决问题的三条规则
如果一个类使用相同的函数签名从多个地方(比如另一个类或接口)继承了方法,通过三条规则可以进行 判断。
(1) 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
(2) 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
(3) 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法,显式地选择使 用哪一个默认方法的实现。