4.7 多重继承
接口允许多重继承,因此有可能碰到两个接口包含签名相同的默认方法的情况。比如例4-19中,接口Carriage和Jukebox都有一个默认方法rock,虽然各有各的用途。类MusicalCarriage同时实现了接口Jukebox(例4-19)和Carriage(例4-20),它到底继承了哪个接口的rock方法呢?
例4-19 Jukebox
public interface Jukebox {public default String rock() {return "... all over the world!";}}
例4-20 Carriage
public interface Carriage {public default String rock() {return "... from side to side";}}public class MusicalCarriage implements Carriage, Jukebox {}
此时,javac并不明确应该继承哪个接口中的方法,因此编译器会报错:class MusicalCarriage inherits unrelated defaults for rock() from types Carriage and Jukebox。当然,在类中实现rock方法就能解决这个问题,如例4-21所示。
例4-21 实现rock方法
public class MusicalCarriageimplements Carriage, Jukebox {@Overridepublic String rock() {return Carriage.super.rock();}}
该例中使用了增强的super语法,用来指明使用接口Carriage中定义的默认方法。此前,使用super关键字是指向父类,现在使用类似InterfaceName.super这样的语法指的是继承自父接口的方法。
三定律
如果对默认方法的工作原理,特别是在多重继承下的行为还没有把握,如下三条简单的定律可以帮助大家。
类胜于接口。如果在继承链中有方法体或抽象的方法声明,那么就可以忽略接口中定义的方法。
子类胜于父类。如果一个接口继承了另一个接口,且两个接口都定义了一个默认方法,那么子类中定义的方法胜出。
没有规则三。如果上面两条规则不适用,子类要么需要实现该方法,要么将该方法声明为抽象方法。
其中第一条规则是为了让代码向后兼容。
