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

\begin{document}
\setcounter{section}{2}
\setlength{\columnsep}{22pt}
\pagestyle{plain}
\sloppy
\tableofcontents
\section{Специализация: ООП и исключения}
\subsection{В предыдущем разделе}
Была рассмотрена реализация объектно-ориентированного программирования в Java. Рассмотрели классы и объекты, а также наследование, полиморфизм и инкапсуляцию. Дополнительно был освещён вопрос устройства памяти.

\subsection{В этом разделе}
В дополнение к предыдущему, будут разобраны такие понятия, как внутренние и вложенные классы; процессы создания, использования и расширения перечислений. Более детально будет разобрано понятие исключений и их тесная связь с многопоточностью в Java. Будут рассмотрены исключения с точки зрения ООП, процесс обработки исключений.
\begin{itemize}
\item \nom{Внутренний класс}{ };
\item \nom{Вложенный класс}{ };
\item \nom{Исключение}{ };
\item \nom{Многопоточность}{ };
\end{itemize}

\subsection{Перечисления}
Кроме восьми примитивных типов данных и классов в Java есть специальный тип, выведенный на уровень синтаксиса языка - \code{enum} или перечисление. Перечисления представляют набор логически связанных констант. Объявление перечисления происходит с помощью оператора \code{enum}, после которого идет название перечисления. Затем идет список элементов перечисления через запятую.

\begin{frm} \info Перечисление -- это упоминание объектов, объединённых по какому-либо признаку \end{frm}

Перечисления -- это специальные классы, содержащие внутри себя собственные статические экземпляры.

\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Пример перечисления}]
enum Season { WINTER, SPRING, SUMMER, AUTUMN }.
\end{lstlisting}

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

Season current = Season.SPRING; System.out.println(current);

Интересно также то, что вывод в терминал и запись в коде у исключений полностью совпадают, поэтому, в терминале мы видим .... 

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

Season[] seasons = Season.values(); for (Season s : seasons) { System.out.printf("s ", s); }

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

% +++ Комментатор_Ильнар. Строго говоря не очень корректная фраза "потому что у перечислений нет индексов". seasons - это уже обычный массив и можно его обойти обычным способом с индексами, скорее мы просто тут показали foreach цикл. 

 Также в перечисления встроен метод ordinal() возвращающий порядковый номер определенной константы (нумерация начинается с 0).

System.out.println(current.ordinal())

Обратите внимание на синтаксис, метод можно вызвать только у конкретного экземпляра перечисления, а при попытке вызова у самого класса перечисления

System.out.println(Seasons.ordinal())

мы ожидаемо получаем ошибку невозможности вызова нестатического метода из статического контекста.

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

 Перечисление Color определяет приватное поле code для хранения кода цвета, а с помощью метода getCode оно возвращается.

enum Color {
    RED("\#FF0000"), GREEN("\#00FF00"), BLUE("\#0000FF");
    String code;
    Color (String code) { this.code = code; }
    String getCode() { return code; }
  }
  
Через конструктор передается для него значение. Следует отметить, что конструктор по умолчанию приватный, то есть имеет модификатор private. Любой другой модификатор будет считаться ошибкой. Поэтому создать константы перечисления с помощью конструктора мы можем только внутри перечисления. И что косвенно намекает нам на то что объекты перечисления это статические объекты внутри самого класса перечисления. Также важно, что механизм описания конструкторов класса работает по той же логике, что и обычные конструкторы, то есть создав собственный конструктор мы уничтожили конструктор по-умолчанию, впрочем, мы его можем создать, если это будет иметь смысл для решаемой задачи.

 Исходя из сказанного ранее можно сделать вывод, что с объектами перечисления можно работать точно также, как с обычными объектами, что мы и сделаем, например, выведя информацию о них в консоль

for (Color c : Color.values()) { System.out.printf("s(s) ", c, c.getCode()); }

\subsubsection{Задания для самопроверки}
\begin{enumerate}
\item Перечисления нужны, чтобы: 3
  \begin{enumerate}
  \item вести учёт созданных в программе объектов;
  \item вести учёт классов в программе;
  \item вести учёт схожих по смыслу явлений в программе;
  \end{enumerate}
\item Перечисление - это: 2
  \begin{enumerate}
  \item массив
  \item класс
  \item объект
  \end{enumerate}
\item каждый объект в перечислении - это: 3
  \begin{enumerate}
  \item статическое поле
  \item статический метод
  \item статический объект
  \end{enumerate}
\end{enumerate}

\subsection*{Практическое задание}
\begin{enumerate}
    \item Написать класс кота так, чтобы каждому объекту кота присваивался личный порядковый целочисленный номер.
\end{enumerate}

\newpage
\printnomenclature[40mm]

\end{document}

% enum Color{
%    RED("#FF0000"), BLUE("#0000FF"), GREEN("#00FF00");
%    private String code;
%    Color(String code){
%        this.code = code;
%    }
%    public String getCode(){ return code;}
% }

%public class Main{
%    public static void main(String[] args) {
%        System.out.println(Color.RED.getCode());        
%        System.out.println(Color.GREEN.getCode());      
%    }
%}


% package ru.gb.jcore;

% public class Orange {

%     public void squeezeJuice(){
%         System.out.println("Squeeze juice ...");
%     }

%     class Juice{
        
%         public void flow(){
%             System.out.println("Juice dripped ...");
%         }
%     }
%     }

% package ru.gb.jcore;

% public class Main {

%     public static void main(String[] args) {
%         Orange orange = new Orange();
%         Orange.Juice juice = orange.new Juice();
%         orange.squeezeJuice();
%         juice.flow();
%     }
%     }
%///////////////////////////////
% public class Orange {

%     private Juice juice;

%     public Orange(){
%         this.juice = new Juice();
%     }

%     public void squeezeJuice(){
%         System.out.println("Squeeze juice ...");
%         juice.flow();
%     }

%     private class Juice{
        
%         public void flow(){
%             System.out.println("Juice dripped ...");
%         }
%     }
% }
% public class Main {

%     public static void main(String[] args) {
%         Orange orange = new Orange();
%         orange.squeezeJuice();
%     }
% }
