\documentclass[j-spec.tex]{subfiles}

\begin{document}
\setcounter{section}{2}
\pagestyle{plain}
\sloppy
\tableofcontents
\section{Специализация: ООП}
\subsection{В предыдущем разделе}
Будет рассмотрен базовый функционал языка, то есть основная встроенная функциональность, такая как  математические операторы, условия, циклы, бинарные операторы. Далее способы хранения и представления данных в Java, и в конце способы манипуляции данными, то есть функции (в терминах языка называющиеся методами).

\subsection{В этом разделе}
Разберём такие основополагающих в Java вещи, как классы и объекты, а также с тем, как применять на практике основные принципы ООП: наследование, полиморфизм и инкапсуляцию. Дополнительно рассмотрим устройство памяти в джава.
\begin{itemize}
\item \nom{Класс}{определяет форму и сущность объекта и является логической конструкцией, на основе которой построен весь язык Java. Определяет новый тип данных};
\item \nom{Объект}{конкретный экземпляр класса, созданный в программе};
\item \nom{Статика}{(статический контекст) static - (от греч. неподвижный) — раздел механики, в котором изучаются условия равновесия механических систем под действием приложенных к ним сил и возникших моментов. В языке программирования Java - принадлежность поля и его значения не объекту, а классу, и, как следствие, доступность такого поля и его значения в единственном экземпляре всем объектам класса.};
\item \nom{Стек}{- };
\item \nom{Куча}{- };
\item \nom{Сборщик мусора}{- };
\item \nom{Конструктор}{- };
\item \nom{Вложенный класс}{- };
\item \nom{Внутренний класс}{- };
\item \nom{Инкапсуляция}{- };
\item \nom{Наследование}{- };
\item \nom{Полиморфизм }{- };
\end{itemize}

\subsection{Классы и объекты, поля и методы, статика}
\subsubsection{Классы}
Что такое класс? С точки зрения ООП, \textbf{класс} определяет форму и сущность объекта и является логической конструкцией, на основе которой построен весь язык Java.

\begin{frm}\info
  Наиболее важная особенность класса состоит в том, что он определяет новый тип данных, которым можно воспользоваться для создания объектов этого типа
\end{frm}

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

Например, если мы хотим работать в нашем приложении с документами, то необходимо для начала объяснить приложению, что такое документ, описать его в виде класса (чертежа) \code{Document}. Указать, какие у него должны быть свойства: название, содержание, количество страниц, информация о том, кем он подписан и т.п. В этом же классе мы обычно описываем, что можно делать с документами: печатать в консоль, подписывать, изменять содержание, название и т.д. Результатом такого описания и будет класс \code{Document}. Однако, это по-прежнему всего лишь чертеж хранимых данных (состояний) и способы взаимодействия с этими данными.

Если нам нужны конкретные документы, а нам они обязательно нужны, то необходимо создавать \textbf{объекты}: документ №1, документ №2, документ №3. Все эти документы будут иметь одну и ту же структуру (описанные нами название, содержание, ...), с ними можно выполнять одни и те же описанные нами действия (печатать, подписать, ...), но наполнение будет разным, например, в первом документе содержится приказ о назначении работника на должность, во втором, о выдаче премии отделу разработки и т.д.

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

\begin{figure}[H]
  \begin{forest}
    for tree={
      font=\ttfamily, grow'=0, child anchor=west,
      parent anchor=south, anchor=west, calign=first,
      edge path={
        \noexpand\path [draw, \forestoption{edge}]
        (!u.south west) +(7.5pt,0) |- node[fill,inner sep=1.5pt]
        {} (.child anchor)\forestoption{edge label};
      }, before typesetting nodes={
        if n=1 {insert before={[,phantom]}} {} },
      fit=band, before computing xy={l=20pt},
    }
    [Sample
     [src
      [ru
       [gb
        [jcore
         [sample
          [Main.java]
          [Cat.java]
         ]
        ]
       ]
      ]
     ]
     [out
     ]
     [README.md]
    ]
  \end{forest}
  \caption{Структура проекта}
  \label{pic:simple-tree}
\end{figure}

\subsubsection{Поля класса}
Начнем описывать в классе \code{Cat} так называемый API кота. Как изестно, имя класса должно совпадать с именем файла, в котором он объявлен, т.е. класс \code{Cat} должен находиться в файле \code{Cat.java}. Пусть у котов есть три свойства: \code{name} (кличка), \code{color} (цвет) и \code{age} (возраст); совокупность этих свойств называется состоянием, и коты пока ничего не умеют делать. Класс \code{Cat} будет иметь вид, представленный в листинге \hrf{lst:class-simple}. Свойства класса, записанные таким образом, в виде переменных, называются \textbf{полями}.

\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Структура кота в программе},label={lst:class-simple}]
package ru.gb.jcore;

public class Cat {
    String name;
    String color;
    int age;
}
\end{lstlisting}

\begin{frm} \excl
Для новичка важно не запутаться, класс кота мы описали в отдельном файле, а создавать объекты и совершать манипуляции следует в основном классе программы, не может же кот назначить имя сам себе.
\end{frm}

Мы рассказали программе, что такое коты, теперь если мы хотим создать в нашем приложении конкретного кота, следует воспользоваться оператором \code{new Cat();} в основном классе программы. Более подробно разберём, что происходит в этой строке, чуть позже, пока же нам достаточно знать, что мы создали объект типа \code{Cat} (экземпляр класса \code{Cat}), и запомнить эту конструкцию. Для того чтобы с ним (экземпляром) работать, можем положить его в переменную, которой дать идентификатор \code{cat1}. При создании объекта полям присваиваются значения по умолчанию (нули для числовых переменных и \code{false} для булевых).

\begin{lstlisting}[language=Java,style=JCodeStyle]
  Cat cat0; // cat0 = null;
  cat0 = new Cat();
  Cat cat1 = new Cat();
\end{lstlisting}

В листинге выше можно увидеть все три операции (объявление, присваивание и инициализацию) и становится понятно, как можно создавать объекты. Также известно, что в переменной не лежит сам объект, а только ссылка на него. Объект \code{cat1} создан по чертежу \code{Cat}, это значит, что у него есть поля \code{name}, \code{color}, \code{age}, с которыми можно работать: получать или изменять их значения.

\begin{frm} \info
  Для доступа к полям объекта используется оператор точка, который связывает имя объекта с именем поля. Например, чтобы присвоить полю \code{color} объекта \code{cat1} значение «Белый», нужно выполнить код \code{cat1.color = "Белый"};
\end{frm}

Операция «точка» служит для доступа к полям и методам объекта по его имени. Мы уже использовали оператор «точка» для доступа к полю с длиной массива, например. Рассмотрим пример консольного приложения, работающего с объектами класса \code{Cat}. Создадим двух котов, один будет белым Барсиком 4х лет, второй чёрным Мурзиком шести лет, и просто выведем информацию о них в терминал.

\begin{lstlisting}[language=Java,style=JCodeStyle]
package ru.gb.jcore;

public class Main {
    public static void main(String[] args) {
        Cat cat1 = new Cat();
        Cat cat2 = new Cat();

        cat1.name = "Barsik";
        cat1.color = "White";
        cat1.age = 4;

        cat2.name = "Murzik";
        cat2.color = "Black";
        cat2.age = 6;

        System.out.println("Cat1 named: " + cat1.name +
                " is " + cat1.color +
                " has age: " + cat1.age);
        System.out.println("Cat2 named: " + cat2.name +
                " is " + cat2.color +
                " has age: " + cat2.age);
    }
}
\end{lstlisting}

в результате работы программы в консоли появятся следующие строки:
\begin{verbatim}
Cat1 named: Barsik is White has age: 4
Cat2 named: Murzik is Black has age: 6
\end{verbatim}

Вначале мы создали два объекта типа \code{Cat}: \code{cat1} и \code{cat2}, соответственно, они имеют одинаковый набор полей \code{name}, \code{color}, \code{age}. Почему? Потому что они принадлежат одному классу, созданы по одному шаблону. Объекты всегда «знают», какого они класса. Однако каждому из них в эти поля записаны разные значения. Как видно из результата печати в консоли, изменение значения полей одного объекта, никак не влияет на значения полей другого объекта. Данные объектов \code{cat1} и \code{cat2} изолированы друг от друга. А значит мы делаем вывод о том, поля хранятся в классе, а значения полей хранятся в объектах. Логическая структура, демонстрирующая отношения объектов и классов, в том числе в части хранения полей и их значений показана на рис. \hrf{pic:class-obj-fields}.

\begin{figure}[H]
  \centering
  \def\svgscale{1.01}
  \fontsize{12}{1}\selectfont
  \includesvg{pics/jc-03-class-obj-fields.svg}
  \caption{Логическая структура отношения класс-объект}
  \label{pic:class-obj-fields}
\end{figure}

\subsubsection{Объекты}
Разобравшись с тем, как создавать новые типы данных (классы) и мельком посмотрев, как создаются объекты, нужно подробнее разобрать, как создавать объекты, и что при этом происходит. Создание объекта как любого ссылочного типа данных проходит в два этапа. Как и в случае с уже известными нам массивами.
\begin{itemize}
\item Сначала создается переменная, имеющая интересующий нас тип, в неё возможно записать ссылку на объект;
\item затем необходимо выделить память под объект;
\item создать и положить объект в выделенную часть памяти;
\item и сохранить ссылку на этот объект в памяти - в нашу переменную.
\end{itemize}

Для непосредственного создания объекта применяется оператор \code{new}, который динамически резервирует память под объект и возвращает ссылку на него, в общих чертах эта ссылка представляет собой адрес объекта в памяти, зарезервированной оператором \code{new}.

\begin{lstlisting}[language=Java,style=JCodeStyle]
  Cat cat1; // cat1 = null;
  cat1 = new Cat();
  Cat cat2 = new Cat();
\end{lstlisting}

В первой строке кода переменная \code{cat1} объявляется как ссылка на объект типа \code{Cat} и пока ещё не ссылается на конкретный объект (первоначально значение переменной \code{cat1} равно \code{null}). В следующей строке выделяется память для объекта типа \code{Cat}, и в переменную \code{cat1} сохраняется ссылка на него. После выполнения второй строки кода переменную \code{cat1} можно использовать так, как если бы она была объектом типа \code{Cat}. Обычно новый объект создается в одну строку, то есть инициализируется.

\subsubsection{Оператор \code{new}}

\begin{frm}\info
[квалификаторы] ИмяКласса имяПеременной = \textbf{\code{new}} ИмяКласса();
\end{frm}

Оператор \code{new} динамически выделяет память для нового объекта, общая форма применения этого оператора имеет вид как на врезке выше, но на самом деле справа - не имя класса, конструкция  ИмяКласса() в правой части выполняет вызов конструктора данного класса, который подготавливает вновь создаваемый объект к работе.

Именно от количества применений оператора \code{new} будет зависеть, сколько именно объектов будет создано в программе.

\begin{lstlisting}[language=Java,style=JCodeStyle]
  Cat cat1 = new Cat();
  Cat cat2 = cat1;

  cat1.name = "Barsik";
  cat1.color = "White";
  cat1.age = 4;

  cat2.name = "Murzik";
  cat2.color = "Black";
  cat2.age = 6;

  System.out.println("Cat1 named: " + cat1.name +
          " is " + cat1.color +
          " has age: " + cat1.age);
  System.out.println("Cat2 named: " + cat2.name +
          " is " + cat2.color +
          " has age: " + cat2.age);
\end{lstlisting}

На первый взгляд может показаться, что переменной \code{cat2} присваивается ссылка на копию объекта \code{cat1}, т.е. переменные \code{cat1} и \code{cat2} будут ссылаться на разные объекты в памяти. Но это не так. На самом деле \code{cat1} и \code{cat2} будут ссылаться на один и тот же объект. Присваивание переменной \code{cat1} значения переменной \code{cat2} не привело к выделению области памяти или копированию объекта, лишь к тому, что переменная \code{cat2} содержит ссылку на тот же объект, что и переменная \code{cat1}. Это явление дополнительно подчёркивает ссылочную природу данных в языке Java.

Таким образом, любые изменения, внесённые в объект по ссылке \code{cat2}, окажут влияние на объект, на который ссылается переменная \code{cat1}, поскольку \textit{это один и тот же объект в памяти}. Поэтому результатом выполнения кода, где мы как будто бы указали возраст второго кота, равный шести годам, станут строки, показывающие, что по обеим ссылкам оказался кот возраста шесть лет с именем Мурзика.

\begin{verbatim}
Cat1 named: Murzik is Black has age: 6
Cat2 named: Murzik is Black has age: 6
\end{verbatim}

\begin{frm}\info
Множественные ссылки на один и тот же объект в памяти довольно легко себе представить как ярлыки для запуска одной и той же программы на рабочем столе и в меню быстрого запуска. Или если на один и тот же шкафчик в раздевалке наклеить два номера - сам шкафчик можно будет найти по двум ссылкам на него.
\end{frm}

Важно всегда перепроверять, какие объекты созданы, а какие имеют множественные ссылки.

\subsubsection{Методы}
Ранее было сказано о том, что в языке Java любая программа состоит из классов и функций, которые могут описываться только внутри них. Именно поэтому все функции в языке Java являются методами. А метод - это функция, являющаяся частью некоторого класса, которая может выполнять операции над данными этого класса.

\begin{frm} \info
  Метод - это функция, принадлежащая классу
\end{frm}

Метод для своей работы может использовать поля объекта и/или класса, в котором определен, напрямую, без необходимости передавать их во входных параметрах. Это похоже на использование глобальных переменных в функциях, но в отличие от глобальных переменных, метод может получать прямой доступ только к членам класса. Самые простые методы работают с данными объектов. Методы чаще всего формируют API классов, то есть способ взаимодействия с классами, интерфейс. Место методов во взаимодействии классов и объектов показано на рис. \hrf{pic:class-obj-nostatic}.

\begin{figure}[H]
  \centering
  \def\svgscale{1.01}
  \fontsize{12}{1}\selectfont
  \includesvg{pics/jc-03-class-obj-nostatic.svg}
  \caption{Логическая структура отношения класс-объект}
  \label{pic:class-obj-nostatic}
\end{figure}

Вернёмся к примеру с котиками. Широко известно, что котики умеют урчать, мяукать и смешно прыгать. В целях демонстрации в описании этих действий просто будем делать разные выводы в консоль, хотя возможно и научить котика в программе выбирать минимальное значение из массива, но это было бы, как минимум, неожиданно. Итак опишем метод например подать голос и прыгать.

\begin{lstlisting}[language=Java,style=JCodeStyle]
public class Cat {
    String name;
    String color;
    int age;

    void voice() {
        System.out.println(name + " meows");
    }

    void jump() {
        if (this.age < 5) System.out.println(name + " jumps");
    }
}
\end{lstlisting}

Обращение к методам выглядит очень похожим на стандартный способом, через точку, как к полям. Теперь когда появляется необходимость позвать котика, он скажет: «мяу, я имя котика», а если в программе пришло время котику прыгнуть, он решит, прилично ли это -- прыгать в его возрасте.

\begin{lstlisting}[language=Java,style=JCodeStyle]
package ru.gb.jcore;

public class Main {
    public static void main(String[] args) {
        Cat cat1 = new Cat();
        Cat cat2 = new Cat();

        cat1.name = "Barsik";
        cat1.color = "White";
        cat1.age = 4;

        cat2.name = "Murzik";
        cat2.color = "Black";
        cat2.age = 6;

        cat1.voice();
        cat2.voice();
        cat1.jump();
        cat2.jump();
    }
}
\end{lstlisting}

\begin{verbatim}
Barsik meows
Murzik meows
Barsik jumps
\end{verbatim}

Как видно, Барсик замечательно прыгает, а Мурзик от прыжков воздержался, хотя попрыгать программа попросила их обоих.

\subsubsection{Ключевое слово \code{static}}
В завершение базовой информации о классах и объектах, остановимся на специальном модификаторе \code{static}, делающем переменную или метод «независимыми» от объекта.

\begin{frm}\info
\textbf{\code{static}} — модификатор, применяемый к полю, блоку, методу или внутреннему классу, он указывает на привязку субъекта к текущему классу.
\end{frm}

Для использования таких полей и методов, соответственно, объект создавать не нужно. В Java большинство членов служебных классов являются статическими. Возможно использовать это ключевое слово в четырех контекстах:
\begin{itemize}
\item статические методы;
\item статические переменные;
\item статические вложенные классы;
\item статические блоки.
\end{itemize}
В этом разделе рассмотрим подробнее только первые два пункта, третий опишем чуть позже, а четвёртый потребует от нас знаний, выходящих не только за этот урок, но и за десяток следующих.

\textbf{Статические методы} также называются методами класса, потому что статический метод принадлежит классу, а не его объекту. Нестатические называются методами объекта. Статические методы можно вызывать напрямую через имя класса, не обращаясь к объекту и вообще объект не создавая. Что это и зачем нужно? Например, умение кота мяукать можно вывести в статическое поле, потому что, например, весной можно открыть окно, не увидеть ни одного экземпляра котов, но зато услышать их, и точно знать, что мяукают не дома и не машины, а именно коты.

\begin{figure}[H]
  \centering
  \def\svgscale{1.01}
  \fontsize{12}{1}\selectfont
  \includesvg{pics/jc-03-class-obj-full.svg}
  \caption{Логическая структура отношения класс-объект}
  \label{pic:class-obj-full}
\end{figure}

Аналогично статическим методам, \textbf{статические поля} принадлежат классу и совершенно ничего «не знают» об объектах.

\begin{frm}\excl
Важной отличительной чертой статических полей является то, что их значения также хранятся в классе, в отличие от обычных полей, чьи значения хранятся в объектах.
\end{frm}

Рисунок \hrf{pic:class-obj-full} именно в этом виде автор настоятельно рекомендует если не заучить, то хотя бы хорошо запомнить, он ещё пригодится в дальнейшем обучении и работе. Из этого же изображения можно сделать несколько выводов.

\begin{lstlisting}[language=Java,style=JCodeStyle]
public class Cat {
    static int pawsCount = 4;

    String name;
    String color;
    int age;

    // ...
}
\end{lstlisting}

Помимо того, что статические поля - это полезный инструмент создания общих свойств это ещ§ и опасный инструмент создания общих свойств. Так, например, мы знаем, что у котов четыре лапы, а не 6 и не 8. Не создавая никакого барсика будет понятно, что у кота - 4 лапы. Это полезное поведение.

лайвкод 03-статическое-поле-ошибка  Посмотрим на опасность. Мы видим, что у каждого кота есть имя, и помним, что коты хранят значение своего имени каждый сам у себя. А знают экземпляры о названии поля потому что знают, какого класса они экземпляры. Но что если мы по невнимательности добавим свойство статичности к имени кота?

03-статическое-поле-признак  Создав тех же самых котов, которых мы создавали весь урок, мы получим двух мурзиков и ни одного барсика. Почему это произошло? По факту переменная у нас одна на всех, и значение тоже одно, а значит каждый раз мы меняем именно его, а все остальные коты ничего не подозревая смотрят на значение общей переменной и бодро его возвращают. Поэтому, чтобы не запутаться, к статическим переменным, как правило, обращаются не по ссылке на объект — cat1.name, а по имени класса — Cat.name.

03-статические-поля  К слову, статические переменные — редкость в Java. Вместо них применяют статические константы. Они определяются ключевыми словами static final и по соглашению о внешнем виде кода пишутся в верхнем регистре.

\subsubsection{Задание для самопроверки}
\begin{enumerate}
  \item Что такое класс?
  \item Что такое поле класса?
  \item На какие три этапа делится создание объекта?
  \item Какое свойство добавляет ключевое слово static полю или методу?
  \begin{enumerate}
    \item неизменяемость;
    \item принадлежность классу;
    \item принадлежность приложению.
  \end{enumerate}
  \item Может ли статический метод получить доступ к полям объекта?
  \begin{enumerate}
    \item не может;
    \item может только к константным;
    \item может только к неинициализированным.
  \end{enumerate}
\end{enumerate}

\subsection{Стек и куча}
\subsection{Сборка мусора}
\subsection{Конструкторы}
\subsection{Инкапсуляция}
\subsection{Наследование}
\subsection{Полиморфизм}

- Также, хотелось бы отметить, что мы можем использовать -Xms и -Xmx опции JVM, чтобы определить начальный и максимальный размер памяти в куче. Для стека определить размер памяти можно с помощью опции -Xss;

\begin{lstlisting}[language=Java,style=JCodeStyle]
public class Cat {
    private String name;
    private String color;
    private int age;

    public Cat() {
        System.out.println("constructor is constructing...");
        name = "Barsik";
        color = "White";
        age = 2;
    }
}
\end{lstlisting}

\begin{lstlisting}[language=Java,style=JCodeStyle]
public class Cat {
    private String name;
    private String color;
    private int age;

    Cat(String n, String c, int a) {
        System.out.println("constructor is constructing...");
        name = n;
        color = c;
        age = a;
    }
}
\end{lstlisting}

\begin{lstlisting}[language=Java,style=JCodeStyle]
  Cat cat1 = new Cat("Barsik", "White", 4);
  Cat cat2 = new Cat("Murzik", "Black", 6);
\end{lstlisting}

\begin{lstlisting}[language=C,style=CCodeStyle]
public class Cat {
    private String name;
    private String color;
    private int age;

    public Cat(String name, String color, int age) {
        this.name = name;
        this.color = color;
        this.age = age;
    }
}
\end{lstlisting}

ключевое слово this в Java используется только в составе экземпляра класса. Но неявно ключевое слово this передается во все методы, кроме статических (поэтому this часто называют неявным параметром) и может быть использовано для обращения к объекту, вызвавшему метод.


\newpage
\printnomenclature[40mm]

\end{document}
