Default Methods in Interfaces
interface Vehicle {
double getSpeed();
default double getSpeedInMiles() {
return getSpeed() * 0.621371;
}
}
static class Car implements Vehicle {
@Override
public double getSpeed() {
return 100;
}
}
public static void main(String[] args) {
Car car = new Car();
System.out.println("Speed in km/h " + car.getSpeed());
// Speed in km/h 100.0
System.out.println("Speed in mph " + car.getSpeedInMiles());
// Speed in mph 62.137100000000004
}
В отличие от обычных методов интерфейса, мы объявляем их с ключевым словом default в начале сигнатуры метода, и они предоставляют реализацию.
Причина, по которой в версию Java 8 включены методы по умолчанию, довольно очевидна.
В типичном проекте, основанном на абстракциях, где интерфейс имеет одну или несколько реализаций, если к интерфейсу добавляется один или несколько методов, все реализации также будут вынуждены их реализовать. В противном случае конструкция просто сломается.
Методы интерфейса по умолчанию — эффективный способ решения этой проблемы. Они позволяют нам добавлять в интерфейс новые методы, которые автоматически доступны в реализациях. Поэтому нам не нужно изменять реализующие классы.
Таким образом, обратная совместимость аккуратно сохраняется без необходимости рефакторинга разработчиков.
На первый взгляд эта функция может показаться немного небрежной, особенно с точки зрения объектно-ориентированного теоретика. В идеале интерфейсы не должны инкапсулировать поведение, и мы должны использовать их только для определения общедоступного API определенного типа.
Однако когда дело доходит до обеспечения обратной совместимости с существующим кодом, методы по умолчанию являются хорошим компромиссом.