Логотип Workflow

Article

Oop Concepts

Тема 5. OOP Concept

ООП это способ управлять сложностью программы, а не просто набор терминов. Когда проект растет, код без границ ответственности становится хрупким: любое изменение задевает соседние части. Принципы ООП нужны, чтобы разделить ответственность, стабилизировать контракты между частями системы и сделать код расширяемым.

OOP pillars

Как смотреть на ООП на практике

Вместо вопроса «что такое ООП» полезнее задавать себе 3 практических вопроса:

  1. Где хранится состояние (данные) и кто имеет право его менять.
  2. Через какие публичные методы другие части системы взаимодействуют с объектом.
  3. Какие внутренние детали можно менять без влияния на внешний код.

Если на эти вопросы есть четкие ответы, архитектура обычно здорова.

Инкапсуляция

Инкапсуляция ограничивает прямой доступ к полям и заставляет менять состояние только через методы с проверками.

Encapsulation

public class BankAccount {
    private double balance;

    public void deposit(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("amount must be > 0");
        }
        balance += amount;
    }

    public void withdraw(double amount) {
        if (amount <= 0 || amount > balance) {
            throw new IllegalArgumentException("invalid withdraw amount");
        }
        balance -= amount;
    }

    public double getBalance() {
        return balance;
    }
}

Что это дает:

  • объект нельзя сломать случайной записью в поле;
  • бизнес-правила централизованы;
  • легче тестировать корректность поведения.

Наследование

Наследование выражает отношение is-a: дочерний класс расширяет базовый и переиспользует его контракт/поведение.

Inheritance

class Animal {
    void speak() {
        System.out.println("...");
    }
}

class Dog extends Animal {
    @Override
    void speak() {
        System.out.println("Woof");
    }
}

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

  • есть стабильная и естественная иерархия;
  • общий контракт действительно общий;
  • замена потомка на базовый тип логически корректна.

Когда осторожно:

  • если нужно только переиспользовать код, часто лучше композиция (has-a), потому что она гибче и проще для изменений.

Полиморфизм

Полиморфизм позволяет писать код к интерфейсу, а реализацию подставлять позже.

Polymorphism

interface PaymentProcessor {
    void pay(double amount);
}

class CardProcessor implements PaymentProcessor {
    public void pay(double amount) {
        System.out.println("Card: " + amount);
    }
}

class PaymentService {
    private final PaymentProcessor processor;

    PaymentService(PaymentProcessor processor) {
        this.processor = processor;
    }

    void process(double amount) {
        processor.pay(amount);
    }
}

Что это дает:

  • расширяемость без переписывания сервиса;
  • удобная подмена реализаций в тестах;
  • меньшая связность между компонентами.

Абстракция

Абстракция скрывает внутреннюю сложность и оставляет снаружи только нужный контракт.

Abstraction

Пример: пользователь класса вызывает send(message), но не знает, как внутри устроены ретраи, сериализация, сеть и логирование.

Инженерный эффект абстракции:

  • наружный код работает с понятным API;
  • внутреннюю реализацию можно менять безопасно;
  • снижается когнитивная нагрузка: каждому слою видна только своя часть сложности.

Как четыре принципа работают вместе

  1. Инкапсуляция защищает состояние.
  2. Абстракция стабилизирует внешний API.
  3. Полиморфизм делает систему расширяемой.
  4. Наследование или композиция переиспользуют поведение.

Итог: ООП это не «красивый стиль», а практический способ сделать код предсказуемым в развитии и безопасным для изменений.

Quiz

Проверьте, что вы усвоили

Авторизуйтесь чтоб пройти тесты