Ответ
Интерфейс определяет контракт (что объект умеет делать), а абстрактный класс — частичную реализацию для родственных объектов (что объект есть и как частично работает).
| Критерий | Интерфейс (до Java 8+) | Абстрактный класс |
|---|---|---|
| Состояние | Только static final константы |
Может иметь поля (состояние) |
| Конструкторы | Нет | Есть |
| Реализация методов | default и static методы (Java 8+) |
Полная или частичная (abstract) |
| Наследование | Класс может реализовать много интерфейсов | Класс может наследовать только один абстрактный класс |
Когда использовать интерфейс:
- Для определения полиморфного поведения, не связанного с иерархией классов (например,
Comparable,Serializable). - Когда несколько несвязанных классов должны реализовать один и тот же контракт.
- Для достижения слабой связанности и тестируемости (внедрение зависимостей через интерфейс).
Пример интерфейса:
public interface PaymentProcessor {
// Контракт
PaymentResult process(PaymentRequest request);
// Реализация по умолчанию (Java 8+)
default boolean validate(PaymentRequest request) {
return request.getAmount() > 0;
}
}
Когда использовать абстрактный класс:
- Когда несколько тесно связанных классов имеют общую логику или состояние.
- Для предоставления шаблонного метода, определяющего скелет алгоритма.
- Для контроля над расширением класса (поскольку наследование — единственное).
Пример абстрактного класса:
public abstract class DataExporter {
// Общее состояние
protected String outputFileName;
// Конструктор
public DataExporter(String fileName) { this.outputFileName = fileName; }
// Частичная реализация
public final void export() {
prepareData();
generateFile(); // Абстрактный шаг
cleanup();
}
protected abstract void generateFile();
}