Ответ
Основные различия выходят за рамки синтаксиса наследования:
| Критерий | Интерфейс (до Java 8+) | Абстрактный класс |
|---|---|---|
| Состояние | Только static final константы |
Может содержать любые поля (состояние объекта) |
| Конструкторы | Не может иметь | Может иметь конструкторы (для инициализации состояния) |
| Модификаторы методов | Неявно public (и abstract до Java 8) |
Любые (protected, private и т.д.) |
| Реализация по умолчанию | default и static методы (с Java 8) |
Полностью реализованные методы |
| Наследование | Класс может реализовать много интерфейсов | Класс может наследовать только один абстрактный класс |
Пример:
// Интерфейс определяет контракт
interface Loggable {
String LOG_PREFIX = "LOG:"; // Константа
void log(); // Абстрактный метод (неявно public)
default void printTimestamp() { // Реализация по умолчанию
System.out.println("Time: " + Instant.now());
}
}
// Абстрактный класс может содержать состояние и общую логику
abstract class Shape {
protected String color; // Поле с состоянием
public Shape(String color) { this.color = color; } // Конструктор
abstract double area(); // Абстрактный метод
public String getColor() { return color; } // Реализованный метод
}
Когда что использовать:
- Интерфейс: Для определения контракта (возможности), который могут реализовать несвязанные классы.
- Абстрактный класс: Для предоставления общей базы с частичной реализацией классам с общим состоянием и поведением.