Java中解决继承和接口默认方法冲突
1)超类优先。如果超类提供了一个具体方法,同名而且有相同参数类型发默认方法会被忽略。
2)接口冲突。如果一个超接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型(不论是否是默认参数)相同的方法,必须覆盖这个方法来解决冲突。
下面来看第二个规则。考虑另一个包含getName方法的接口:
interface Named { default String getName(){ return getClass().getName() + "_" + hashCode():} }
如果有一个类同时实现了这两个接口会怎么样呢?
class Student implements Person,Named { ... }
类会继承Person和Named接口提供的两个不一致的getName方法。并不是从中选择一个,Java编译器会报告一个错误,让程序员来解决这个二义性。只需要在Student类中提供一个getName方法,在这个方法中,可以选择两个冲突方法中发一个,如下所示:
1 class Student implements Person,Named 2 { 3 public String getName(){ return Person.suoer.getName();} 4 ... 5 }
现在假设Named接口没有为getName提供默认实现:
interface Named { String getName(); }
Students类会从Person接口继承默认方法吗?这好像挺有道理,不过,Java设计者更强调一致性。两个接口如何冲突并不重要。如果至少有一个接口提供了一个实现,编译器就会报告错误,而程序员就必须解决这个二义性。
我们只讨论了两个接口的命名冲突。现在来考虑另一种情况,一个类扩展了一个超类,同时实现了一个接口,并从超类和接口继承了相同的方法。例如,假设Person是一个类,Student定义为:
class Student extends Person implements Named{...}
在这种情况下,只会考虑超类方法,接口的所有默认方法都会被忽略。在我们的例子中,Student从Person继承了getName方法,Named接口是否为getName提供了默认实现并不会带来什么区别。这正是“类优先”规则。