# 2. Базовые термины ООП

**Объектно-ориентированное программирование** – это методология программирования, основанная на представлении программы в виде совокупности взаимодействующих **объектов**, каждый из которых является экземпляром определенного **класса**, а классы являются членами определенной иерархии **наследования**.

**Объект** – структура, которая объединяет данные и методы, которые эти данные обрабатывают. Фактически, объект является основным строительным блоком объектно-ориентированных программ.

**Класс** – шаблон для объектов. **Каждый объект является экземпляром** (*instance*) **какого-либо класса** («безклассовых» объектов не существует). В рамках класса задается общий шаблон, структура, на основании которой создаются объекты. Данные, относящиеся к классу, называются полями класса, а программный код для их обработки называется методами класса. Поля и методы иногда называют общим термином – **члены класса**.

Разница между классом и объектом такая же, как между абстрактным понятием и реальным объектом.

&#x20;Объект состоит из следующих частей:

* **имя** объекта;
* **состояние** (переменные состояния). Данные, содержащиеся в объекте, представляют его состояние. В терминологии ООП эти данные называются атрибутами. Например, атрибутами работника могут быть: имя, фамилия, пол, дата рождения, номер телефона. В разных объектах атрибуты имеют разное значение. Фактически, в объектах определяются конкретные значения тех переменных (полей класса), которые были заявлены при описании класса;
* **методы** (операции) – применяются для выполнения операций с данными, а также для совершения других действий. Методы определяют, как объект взаимодействует с окружающим миром.

Объекты могут отправлять друг другу сообщения. **Сообщение** (message) - это практически то же самое, что и вызов функции в обычном программировании. В ООП обычно употребляется выражение "послать сообщение" какому-либо объекту. Понятие "сообщение" в ООП можно объяснить с точки зрения ООП: мы не можем напрямую изменить состояние объекта и должны как бы послать сообщение объекту, что мы хотим как-то изменить его состояние. Очень важно понять, что объект сам меняет свое состояние, а мы можем только попросить его об этом с помощью отсылки сообщения.

**В объектно-ориентированной программе весь код должен находиться внутри классов!**&#x20;

В классе описываются, какого типа данные относятся к классу, а также то, какие методы применяются к этим данным. Затем, в программе на основе того или иного класса создается экземпляр класса (объект), в котором указываются конкретные значения полей и выполняются необходимые действия над ними.

## От языка С к объектно-ориентированному программированию

Давайте попробуем понять, что такое объект и класс с помощью языка программирования C.

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

Мы можем воспользоваться массивами и хранить данные о книгах в нескольких массивах.

```c
    int book_year[100];
    int book_pages[100];
    char book_author[100][50];
    char book_title[100][100];
    float book_price[100];
```

Теперь мы можем обратиться к i-му номеру каждого массива для получения информации об i-ой книге.

```c
printf("%s-%s %d page", book_author[3], book_title[3], book_pages[3]);
```

Какими недостатками обладает данный способ работы с данными? Такой подход может приводить к многочисленным ошибкам (например, ошибки при работе с индексами массивов), такие данные тяжело модифицировать (удаление книги приводит к необходимости смещать влево часть элементов массивов), такой код неудобно читать, поддерживать и модифицировать.

Но самое главное - **мы мыслим в контексте структуры компьютера, а не решаемой задачи**. Для нас книга - это некий единый объект, который имеет некоторые параметры (атрибуты): название, количество страниц и так далее. Мы же представляем атрибуты этого объекта в виде отдельных записей в разных массивах, потому что на языке C мы вынуждены мыслить в терминах имеющихся структур данных (массивов, очередей, деревьев), а не в терминах отдельных объектов и их взаимоотношений. Это затрудняет понимание решаемой задачи (управление книжной лавкой и продажей книг), увеличивает количество ошибок в программе и на некотором этапе мы вообще перестаем понимать, что происходит в программе.

Для хотя бы какого-то решения этой проблемы и облегчения труда программиста, на некотором этапе в язык C было введено понятие **структуры** (ключевое слово `struct`), которое вы должны были изучать в курсе "Алгоритмизация и программирование".

Структура в языке C - это тип данных, создаваемый программистом, предназначенный для объединения данных различных типов в единое целое. Таким образом, мы можем сгруппировать данные, которые относятся к одной книге, в одну структуру.

Сначала мы должны описать структуру (новый тип данных).

```c
struct Book {
    char author[50];
    char title[100];
    int year;
    int pages;
    float price;
};
```

Таким образом, некоторое понятие реального мира (то есть, книга вообще, как понятие) в программе описан структурой `Book`. Экземпляр этого понятия (какая-то конкретная книга) в программе будет представлен экземпляром структуры - переменной типа `Book`. Мы объявляем экземпляр структуры, после чего мы сможет заполнить поля структуры и работать с ней дальше в программе.

```c
int main() {

    // Объявляем экземпляр структуры
    struct Book book1;

    // Заполняем поля экземпляра
    strcpy(book1.author,"Иванов А.А");
    strcpy(book1.title,"Программирование на Java");
    book1.pages = 255;
    book1.price = 350.25;
    book1.year = 2018;

    // Теперь мы можем работать с созданным экземпляром структуры
    printf("%s - %s, %d страниц", book1.author, book1.title, book1.pages);

    return 0;
}
```

Использование структур решает проблему лишь частично. Мы сгруппировали данные, но функции для работы с нашей структурой находятся вне структуры.&#x20;

Объект реального мира обладает не только атрибутами (автор книги, название книги, количество страниц и так далее), но и определенным поведением (книгу можно продать, купить, переместить на склад и так далее). При разработке сложных программных систем необходимо группировать не только данные, но и функции, которые работают с этими данными.

## Пример использования объектного подхода

*Рассмотрим простой пример объектно-ориентированной программы. Представим, что мы программируем графический редактор, который может рисовать различные фигуры. Подумав над задачей, мы приходим к выводу, что в нашей программе должны быть объекты, которые представляют различные фигуры. Итак приступим.*

Сначала мы должны создать классы и описать внутри этих классов данные, которые относятся к фигурам и поведение фигур в виде набора методов (функций).

Опишем класс для фигуры «Треугольник». Какие характеристики могут быть у класса «Треугольник»? От чего зависит набор характеристик? В принципе, любой объект является бесконечно сложным и для его описания понадобится бесконечно большое количество характеристик. Но для нашего простого графического редактора важными будут следующие параметры: координаты трех точек и цвет фигуры.&#x20;

*Здесь вы должны понять очень важную вещь: набор данных в классе зависит от той программы, которую мы собираемся написать. Например, если бы мы писали более мощный графический редактор, в списке полей класса мы добавили бы отдельно цвет заливки и цвет линий фигуры, сам цвет мог быть не только сплошным, но и в виде какого-то узора и так далее.*

Для указания класса в Java используется ключевое слово `class`, после чего идет название класса, далее мы ставим фигурные скобки и всё, что будет написано внутри фигурных скобок (переменные и функции) будет относиться к этому классу.

```java
class Triangle {
    
}
```

Какие переменные и типы данных будут моделировать координаты точек и цвет? Для моделирования цвета воспользуемся обычным целым числом (очень часто цвета моделируются обычным целочисленным значением).

```java
class Triangle {
    
    // Цвет треугольника
    int color;
}
```

Теперь попробуем подумать, а как нам смоделировать координаты трех точек? Если бы мы программировали на языке C, мы бы написали что-то вроде

```java
class Triangle {

    // Цвет треугольника
    int color;

    // Координаты точек треугольника
    int x1,y1,x2,y2,x3,y3;
}
```

Но давайте подумаем - координаты каждой точки логически связаны между собой и когда мы будем, например, перемещать треугольник или будем менять размер треугольника, будут одновременно меняться две переменные, которые моделируют одну точку. С точки зрения объектной модели, лучшим вариантом будет предусмотреть отдельную сущность, отдельный класс, который моделирует точку на двумерной плоскости. Таким образом, мы сгруппируем данные и код, который будет эти данные изменять (например, менять значение X и Y).

```java
class Point2D {
    
    int x;
    int y;
}
```

Теперь вернемся к классу `Triangle` и укажем, что в качестве координат у нас будут выступать три объекта класса `Point2D`.

```java
class Triangle {

    // Цвет треугольника
    int color;

    // Координаты трех точек
    Point2D point1;
    Point2D point2;
    Point2D point3;
}
```

Теперь давайте определимся с методами классов – то есть, к тому поведению, которое будут осуществлять объекты этих классов.

Какое поведение может быть у объекта класса «точка»? Совершенно точно это будет метод «изменить координаты». То есть, наша точка как отдельный объект может вести себя следующим образом – менять свои координаты. Давайте запрограммируем этот метод.

```java
class Point2D {

    int x;
    int y;

    void changeCoordinates(int new_x, int new_y) {
        x = new_x;
        y = new_y;
    }
}
```

Теперь давайте подумаем, какое поведение будет у треугольника? Что с ним можно сделать? Ну, например, можно его перекрасить, можно его передвинуть в другое место на плоскости, можно его нарисовать на каком-то полотне и так далее. Давайте опишем некоторые из этих методов.

```java
class Triangle {

    int color; // Цвет треугольника

    // Координаты трех точек
    Point2D point1;
    Point2D point2;
    Point2D point3;

    // Меняем цвет фигуры
    void changeColor(int new_color) {
        color = new_color;
    }

    // Меняем расположение фигуры
    // Для наглядности будем передавать входные параметры
    // в виде 6 целых чисел
    void move(int x1, int y1, int x2, int y2, int x3, int y3) {
        point1.changeCoordinates(x1, y1);
        point2.changeCoordinates(x2, y2);
        point3.changeCoordinates(x3, y3);
    }
}
```

&#x20;Итак, мы описали треугольник, но мы определили только понятие «треугольник», у нас нет их физически, код класса - это просто описание. Если вы создали java-проект, у вас, по умолчанию, будет присутствовать класс `Main`и функция `main()`. Пока что мы не будем объяснять, зачем нужен класс `Main`, а обратим внимание на метод `main()`. Этот метод является «точкой входа» в программу, с вызова этого метода начинается работа программы. Когда мы дойдем и выполним последнюю инструкцию внутри метода `main()`, приложение завершится.

Создадим внутри метода `main()` несколько объектов класса `Triangle`. Создание объектов мы будем рассматривать подробно в следующих лекциях, на данный момент мы просто скажем, что для создания объекта используется ключевое слово`new`. После создания объекта, мы можем обращаться к объекту и вызывать методы у объектов (как мы вызывали функции в C).

```java
public class Main {

    public static void main(String[] args) {

        // Создали один объект треугольника
        Triangle triangle1 = new Triangle();

        // Создали еще один объект треугольника
        Triangle triangle2 = new Triangle();

        // Для первого треугольника поменяли цвет
        triangle1.changeColor(10000);
        // Поменяли цвет для второго треугольника
        triangle2.changeColor(20000);

        // Создали объект первой точки треугольника
        // и назначили точке какие-то координаты
        triangle1.point1 = new Point2D();
        triangle1.point1.changeCoordinates(140,180);

        // Сделаем это же для первой точки второго треугольника
        triangle2.point1 = new Point2D();
        triangle2.point1.changeCoordinates(50,80);
    }
}
```

{% hint style="info" %}
**Важно! Вы должны понять, что у разных объектов значения переменных будут разные!**
{% endhint %}

То есть, где-то в оперативной памяти у нас создано два разных объекта. Внутри первого есть объект класса `Point2D`, внутри этого объекта есть две переменные типа `int`, у которых будут значения 140 и 180. Внутри же второго треугольника будет свой объект `Point2D`, внутри которого будут совершенно другие две переменные типа `int`, у которых будут значения 50 и 80. Это же будет касаться переменных color в двух разных объектах (рис.1.5).

![](/files/-Lni03f1YRgWGlIcUFHX)

Таким образом, когда мы описываем классы, мы заявляем, что объекты этих классов будут содержать определенные поля (набор переменных) и будут иметь набор методов (функций), которые можно вызвать у объекта. Каждый объект содержит свои переменные, но методы у них общие.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://opu.gitbook.io/oop/2019-2020-archive/arkhiv-1/lectures/basics.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
