Каждый подкласс должен определять свою собственную реализацию, потому что каждый подкласс может выполнять операцию немного по-разному. Рассмотрим следующий пример:
public interface animal {
//All implementers must define this method
void speak();
}
В этом интерфейсе говорится, что любое животное ДОЛЖНО иметь возможность говорить. В принципе, любой тип животного будет способен шуметь. Затем у нас есть 2 подкласса или 2 разных типа животных, которые мы создаем.
public class Dog implements animal {
//Define how a Dog speaks
public void speak() {
System.out.println( "woof" );
}
}
Затем мы определяем другое животное, кошка
public class Cat implements animal {
//Define how a Cat speaks
public void speak() {
System.out.println( "meow" );
}
}
В этом примере и Кот, и Собака - животные, и поэтому должны иметь возможность говорить благодаря нашему интерфейсу. Однако все знают, что кошки и собаки издают разные звуки. Позволяя каждому подклассу определять, как он «говорит», мы можем дать Собакам и Кошкам их собственный соответствующий звук при вызове метода speak (), при этом они оба являются животными.
В ответ на ваш вопрос более конкретно, наследование заставляет его подклассы иметь определенный метод. Другими словами, интерфейс утверждает, что «все мои подклассы будут определять каждый из этих методов». Это позволяет нам писать код, который имеет дело с методами интерфейса, не зная конкретного подкласса. Мы можем сделать это безопасно, потому что знаем, что каждый подкласс ДОЛЖЕН определить метод в классе интерфейса. Если бы только подклассы, которые используют метод, определяли его, то у нас не было бы способа узнать наверняка, безопасно ли вызывать метод на всех подклассах.
Просто примечание: если вы не хотите, чтобы подкласс определял метод, вы можете просто определить пустой метод следующим образом:
public class MuteAnimal implements animal {
//A MuteAnimal can't speak!
public void speak() { }
}