В вашем примере move()
относится к интерфейсу Vehicle
и определяет контракт "переход от точки A к точке B".
Когда GroundVehicle
и WaterVehicle
расширяются Vehicle
, они неявно наследуют этот контракт (аналогия: List.contains
наследует свой контракт от Collection.contains
- представьте, если он указал что-то другое!).
Таким образом, когда бетон AmphibianVehicle
реализует move()
, контракт, который он действительно должен соблюдать, это Vehicle
. Есть бриллиант, но контракт не меняется, рассматриваете ли вы одну сторону бриллианта или другую (или я бы назвал это проблемой дизайна).
Если вам нужен контракт «перемещения» для воплощения понятия поверхности, не определяйте его в типе, который не моделирует это понятие:
public interface GroundVehicle extends Vehicle {
void ride();
}
public interface WaterVehicle extends Vehicle {
void sail();
}
(аналогия: контракт get(int)
определяется интерфейсом List
. Он не может быть определен Collection
, поскольку коллекции не обязательно упорядочены)
Или рефакторинг вашего общего интерфейса, чтобы добавить понятие:
public interface Vehicle {
void move(Surface s) throws UnsupportedSurfaceException;
}
Единственная проблема, которую я вижу при реализации нескольких интерфейсов, - это когда два метода из совершенно не связанных между собой интерфейсов сталкиваются:
public interface Vehicle {
void move();
}
public interface GraphicalComponent {
void move(); // move the graphical component on a screen
}
// Used in a graphical program to manage a fleet of vehicles:
public class Car implements Vehicle, GraphicalComponent {
void move() {
// ???
}
}
Но тогда это не был бы бриллиант. Больше похоже на перевернутый треугольник.