ООП ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-07-24

Процедурное и объектно-ориентированное программирование

Выделяют две основные методики программирования: процедурное и объектно-ориентированное. Разница между ними не в синтаксисе, а в том, вокруг чего строится программа: вокруг последовательности действий или вокруг объектов, которые эти действия выполняют.

Что такое процедурное программирование

Процедурное программирование — это методика, при которой программа описывается как последовательность инструкций, выполняемых сверху вниз, а порядок выполнения меняют ветвления (if, switch) и циклы (for, while). Когда инструкций становится много, повторяющиеся куски выносят в отдельные подпрограммы — их называют процедурами, функциями или, в Java, методами.

Данные при этом живут отдельно от кода: есть переменные, и есть методы, которые эти переменные принимают и возвращают. Такой подход, дополненный правилом «только последовательность, ветвление и цикл, без goto», называют структурным программированием.

Все программы, которые мы рассматривали до этого урока, написаны именно в процедурном стиле — несмотря на то, что код физически находится внутри класса. Класс здесь работает просто как контейнер для метода main.

Проблема появляется с ростом программы: когда методов становятся десятки, а общих данных — сотни, любое изменение структуры данных заставляет править все методы, которые с ними работают. Разделения на методы уже недостаточно.

Процедурные языки программирования

Процедурный язык программирования — это язык, в котором базовой единицей построения программы является процедура (функция), а не объект. К классическим процедурным языкам относят:

  • C — самый известный процедурный язык, до сих пор используется в системном программировании и ядре Linux;
  • Pascal — язык, созданный для обучения структурному программированию;
  • Fortran — научные и инженерные расчёты;
  • COBOL — банковские и учётные системы, до сих пор в эксплуатации;
  • BASIC, Ada, Go (Go поддерживает методы у типов, но не имеет классов и наследования).

Важно понимать: деление языков на «процедурные» и «объектно-ориентированные» условно. Большинство современных языков — мультипарадигменные. На C++, Python, JavaScript, PHP можно писать и процедурно, и объектно-ориентированно. Java ближе всего к чисто объектно-ориентированным языкам, но и на ней несложно писать процедурный код.

Что такое ООП

Объектно-ориентированное программирование (ООП) — методика программирования, в которой основными понятиями являются объект и класс. Прежде чем писать инструкции, в задаче выделяют объекты и описывают их с помощью классов. В классе задают характеристики объекта (поля класса) и его поведение (методы). Данные и работающий с ними код объединяются в одном месте.

ООП — одна из ключевых особенностей языка Java: в ней нельзя написать метод вне класса, а почти вся стандартная библиотека построена на классах и интерфейсах.

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

Важно

Java не является «на 100 % объектно-ориентированным» языком, как иногда пишут. Примитивные типы (int, double, boolean) объектами не являются, а static-методы вызываются без создания экземпляра. Именно поэтому весь код, написанный внутри main, остаётся процедурным.

Одна задача в двух стилях: пример на Java

Посчитаем стоимость покупки. Сначала — процедурно: данные лежат в переменных, метод получает их параметрами.

public class Main {

    public static void main(String[] args) {
        String name = "Coffee";
        double price = 120.0;
        int quantity = 3;

        System.out.println(name + ": " + total(price, quantity));
    }

    static double total(double price, int quantity) {
        return price * quantity;
    }
}

Теперь то же самое в объектно-ориентированном стиле: данные и поведение объединены в классе Product, а цена скрыта за модификатором private.

public class Product {

    private final String name;
    private final double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public double total(int quantity) {
        return price * quantity;
    }

    public String getName() {
        return name;
    }
}
public class Main {

    public static void main(String[] args) {
        Product coffee = new Product("Coffee", 120.0);
        System.out.println(coffee.getName() + ": " + coffee.total(3));
    }
}

Результат одинаковый, но во втором варианте цена не может быть случайно испорчена снаружи, а правило расчёта стоимости лежит рядом с данными, которые оно использует. Добавление скидки или налога потребует изменить один класс, а не все места вызова.

Четыре принципа ООП

ООП в Java обычно описывают через четыре принципа: абстракцию, инкапсуляцию, наследование и полиморфизм (иногда абстракцию не выделяют отдельно, и остаются три). Подробный разбор каждого принципа с примерами кода и вопросами с собеседований — в отдельном уроке: Принципы ООП в Java.

Агрегация и композиция

Кроме наследования, классы можно связать отношением «имеет» (has-a) — агрегацией (слабая связь: объект получает готовую ссылку извне и живёт независимо) или композицией (жёсткая связь: вложенный объект создаётся владельцем и не существует без него). Разбор с примерами кода на Java — в уроке Ассоциация, агрегация и композиция.

Сравнение подходов

Критерий Процедурное программирование ООП
Базовая единица Процедура (метод, функция) Класс и объект
Данные и поведение Разделены: данные передаются в методы Объединены внутри класса
Доступ к данным Часто открытый, легко испортить извне Скрыт инкапсуляцией (private + методы)
Повторное использование Копирование или вызов функций Наследование, композиция, интерфейсы
Рост требований Правки расползаются по всей программе Изменения локализованы в классе
Порог входа Низкий, результат виден сразу Выше: нужно проектирование до кода
Типичные языки C, Pascal, Fortran, COBOL Java, C#, Kotlin, Smalltalk
Где уместно Скрипты, расчёты, учебные задачи Крупные приложения с долгой поддержкой

Когда процедурный стиль уместнее

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

Признаки того, что пора переходить к объектам: у вас появляется несколько переменных, которые всегда передаются вместе; один и тот же набор данных обрабатывается в разных местах программы; появляются варианты поведения, различающиеся типом сущности. Здесь начинается проектирование классов.

Неочевидный момент

Наличие классов в коде ещё не делает его объектно-ориентированным. Если класс содержит только публичные поля без методов, а вся логика лежит в одном большом static-методе, это процедурная программа, записанная синтаксисом Java. Такой класс-пустышку называют анемичной моделью.

Часто задаваемые вопросы

Сколько принципов ООП — три или четыре?

Оба ответа встречаются: классическая четвёрка — абстракция, инкапсуляция, наследование, полиморфизм, но иногда абстракцию не считают отдельным принципом, и остаются три. Подробный разбор — в уроке Принципы ООП в Java.

Чем процедурное программирование отличается от функционального?

В процедурном стиле процедуры меняют состояние: переменные и поля перезаписываются по ходу выполнения. В функциональном упор на неизменяемые данные и функции без побочных эффектов, а функции можно передавать как аргументы. В Java функциональные приёмы доступны через лямбда-выражения и Stream API, но парадигма языка остаётся объектно-ориентированной.

Что выбрать — наследование или композицию?

По умолчанию композицию: она гибче и не связывает классы так жёстко, как наследование. Разбор отношений между классами с примерами кода — в уроке Ассоциация, агрегация и композиция.

Как переписать процедурный код в объектно-ориентированный?

Найдите переменные, которые всегда передаются вместе, и соберите их в класс. Перенесите туда методы, которые эти переменные принимали, и удалите из сигнатур ставшие лишними параметры. Закройте поля модификатором private и оставьте наружу только те методы, которые нужны вызывающему коду. Метод main в итоге должен превратиться в несколько строк, создающих объекты и запускающих сценарий.

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

Комментарии

Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.