← Назад к вопросам

В чем разница между abstract class и interface?

1.2 Junior🔥 271 комментариев
#ООП

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Abstract Class vs Interface: фундаментальные различия

Это один из самых важных вопросов в Java, потому что выбор между абстрактным классом и интерфейсом кардинально влияет на дизайн системы.

Быстрое сравнение

ПараметрAbstract ClassInterface
НаследованиеОдин класс (IS-A)Много интерфейсов (CAN-DO)
КонструкторМожет бытьНе может быть
ПоляЛюбые (final, static)Только public static final
МетодыЛюбые (public, private, protected)public (default с Java 9)
СостояниеМожет иметь состояниеНе может (только константы)
НазначениеОпределить "что это"Определить "что оно может делать"

Пример 1: IS-A vs CAN-DO (основное различие)

Abstract Class (IS-A отношение):

// "Это животное"
abstract class Animal {
    private String name;
    private int age; // СОСТОЯНИЕ
    
    // Конструктор — инициализируем состояние
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // Абстрактный метод — каждое животное по-своему
    abstract void makeSound();
    
    // Конкретный метод — может быть у всех животных
    public void sleep() {
        System.out.println(name + " is sleeping");
    }
    
    // Protected методы — только для наследников
    protected void grow() {
        age++;
    }
}

// Наследование: Dog ЭТО Animal
class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age); // Инициализируем состояние родителя
    }
    
    @Override
    void makeSound() {
        System.out.println("Woof!");
    }
}

Interface (CAN-DO отношение):

// "Это может летать"
interface Flyable {
    void fly();
    void land();
}

// "Это может плавать"
interface Swimmable {
    void swim();
    void dive();
}

// Класс может ДЕЛАТЬ много вещей
class Duck implements Flyable, Swimmable {
    @Override
    public void fly() {
        System.out.println("Duck is flying");
    }
    
    @Override
    public void swim() {
        System.out.println("Duck is swimming");
    }
}

Пример 2: Состояние (State)

Abstract Class может иметь состояние:

abstract class Vehicle {
    // Состояние — переменные экземпляра
    private int speed;
    private String color;
    
    protected void accelerate(int amount) {
        this.speed += amount; // Изменяем состояние
    }
}

Interface НЕ может иметь состояние:

interface Drivable {
    // Только константы
    int MAX_SPEED = 200;
    
    void drive();
}

Пример 3: Конструкторы

Abstract Class может иметь конструктор:

abstract class DatabaseConnection {
    private String url;
    
    // Конструктор
    protected DatabaseConnection(String url) {
        this.url = url;
    }
}

Interface НЕ может иметь конструктор:

public interface Serializable {
    // Конструктор запрещен!
}

Пример 4: Доступ (Access Modifiers)

Abstract Class — разные уровни доступа:

abstract class BankAccount {
    private double balance; // private
    protected void deposit(double amount) { } // protected
    public void withdraw(double amount) { } // public
    abstract double calculateInterest(); // abstract
}

Interface — все методы public:

public interface PaymentProcessor {
    void processPayment(BigDecimal amount); // public
    
    default void logTransaction(String id) { } // default с Java 9
}

Пример 5: Множественное наследование

Abstract Class — только один родитель:

// Ошибка!
// class Dog extends Animal, Mammal { }

// Правильно:
class Dog extends Animal { }

Interface — много интерфейсов:

// Правильно!
class Bird implements Flyable, Eatable, Observable {
    @Override
    public void fly() { }
    
    @Override
    public void eat() { }
    
    @Override
    public void observe() { }
}

Когда использовать что

Abstract Class когда:

// 1. IS-A отношение
abstract class PaymentMethod { }

// 2. Общая реализация
abstract class Repository<T> {
    public List<T> findAll() { /* общая */ }
}

// 3. Состояние (не константы)
abstract class HttpRequest {
    private String url;
    private Map<String, String> headers;
}

// 4. Разные уровни доступа
abstract class Service {
    private void internalValidation() { }
    protected void preprocessData() { }
}

Interface когда:

// 1. CAN-DO отношение
interface Comparable<T> {
    int compareTo(T o);
}

// 2. Контрактная гарантия
interface DataSource {
    Connection getConnection();
    void close();
}

// 3. Множественное наследование
class FileProcessor implements Runnable, Closeable, Comparable { }

Практический пример

// АБСТРАКТНЫЙ КЛАСС: базовая реализация
abstract class BaseRepository<T> {
    protected JdbcTemplate jdbc;
    
    public void save(T entity) { /* ... */ }
    
    abstract String getTableName();
    abstract T mapRow(ResultSet rs);
}

// ИНТЕРФЕЙСЫ: контракты
interface Cacheable { void clearCache(); }
interface Auditable { void logChange(String field, Object old, Object newVal); }

// КОНКРЕТНЫЙ КЛАСС
class UserRepository extends BaseRepository<User> 
    implements Cacheable, Auditable {
    
    @Override
    String getTableName() { return "users"; }
    
    @Override
    User mapRow(ResultSet rs) { return new User(/* ... */); }
    
    @Override
    public void clearCache() { /* ... */ }
    
    @Override
    public void logChange(String field, Object old, Object newVal) { /* ... */ }
}

Вывод

Abstract Class:

  • IS-A отношение (Dog ЭТО Animal)
  • Общая реализация и состояние
  • Один родитель
  • Разные уровни доступа

Interface:

  • CAN-DO отношение (что может делать)
  • Только контракт
  • Множественное наследование
  • Все методы public

Правильный выбор — основа хорошей архитектуры.