Father
здесь не проблема, поскольку статические методы от интерфейсов не наследуются (например, List.of(..)
не может быть вызвано через ArrayList.of(..)
), поэтому существует нет переопределения / скрытия, что также означает отсутствие столкновений.
Из-за этого мы можем смело писать
interface Father {
static void method() { }
}
interface Child extends Father {
static void method() { }
}
Проблема - это метод default void method() { }
из интерфейса Mother
, который наследуется Child
, что означает, что после
interface Child extends Father, Mother {
static void method() { }
}
В итоге вы получите интерфейс, который будет иметь две версии method()
: статическую и нестатическую (по умолчанию)
interface Child extends Father, Mother {
static void method() { }
default void method() { } //inherited from Mother
}
Но почему это проблема?
Представьте, что вы хотите добавить еще один метод в интерфейс Child
, который будет вызывать method()
interface Child extends Father, Mother {
static void method() { }
default void method() { } //inherited from Mother
default void demo(){
method(); //which code block should be executed?
}
}
Должен ли он выполнять код из static method () или из default method ()? Компилятор не сможет решить.
Хотя эту ситуацию можно решить с помощью
Child.method()
для статического метода,
this.method()
для метода по умолчанию (да, он не будет неоднозначным, потому что статический метод не будет наследоваться классом, экземпляр которого this
будет экземпляром),
Дело в том, чтобы предотвратить подобные проблемы в первую очередь. Вот почему мы должны не иметь статических и нестатических методов с одинаковыми сигнатурами (name + parameterTypes) в одном месте (определенном или унаследованном).