Ранее никогда не писал собственные интерфейсы для "упрощения жизни". Почему? Что в них такого интересного? В комментариях попросили добавить в вопрос мои знания и область работы. Пишу android приложения и... Все. Об интерфейсах не знаю ничего, только то, что можно класс от интерфейса наследовать и переопределить методы. Но зачем? Смысл интерфейсов? Спасибо за замечательные ответы!
Ответ Интерфейс предоставляет контракт, который должны выполнять все классы, реализующие этот интерфейс, и является абстракцией, показывающей что объект может делать, но как он этот делает - не важно. На практике это приводит к следующему: При использовании интерфейсов появляется возможность заменять один класс, реализующий интерфейс, на другой класс, реализующий этот же интерфейс, без переписывания всего кода. Например, если методу передаётся Map: public void handle(Map map) { ... } то не придётся менять описание метода, если потребуется использовать TreeMap вместо HashMap. Аналогично если метод возвращает Map: он может начать возвращать TreeMap вместо HashMap, и трагедии библейских масштабов при этом не случится, так как код, работающий с возвращенным этим методом значением, имеет дело с Map. Это увеличивает гибкость кода: проще переключаться с одного источника данных на другой и с одной реализации на другую. Также это полезно при тестировании, так как позволяет использовать Mock-объекты вместо настоящих.
Если нужно одинаково обрабатывать коллекции элементов (например, ArrayList и Set, возвращаемый методом keySet() у HashMap), то достаточно описать метод так: public void handle(Collection elements) { ... } Использование generics-типа здесь для большей реалистичности. Без использования интерфейса пришлось создавать два метода: public void handle(ArrayList elements) { ... } public void handle(Set elements) { ... } И либо дублировать код, либо, например, во втором методе создавать ArrayList, добавлять в него все элементы из Set и вызывать первый метод.
Также использование интерфейсов позволяет объединить разные объекты, реализующий один и тот же интерфейс, в один список и одинаково их обрабатывать: public interface Animal { public void feed() } public class Dog implements Animal { public void feed() { ... } } public class Cat implements Animal { public void feed() { ... } } List animals = new ArrayList<>() animals.add(new Cat()) animals.add(new Dog()) for (Animal animal : animals) { animal.feed() } Без использования интерфейса пришлось бы городить "if-else" (или "switch-case") с отдельной реализацией логики для каждого типа животных.