diff --git a/build/jc3-03.pdf b/build/jc3-03.pdf index d746fd4..9540506 100644 Binary files a/build/jc3-03.pdf and b/build/jc3-03.pdf differ diff --git a/jc3-03.tex b/jc3-03.tex index a72ea67..a78712a 100644 --- a/jc3-03.tex +++ b/jc3-03.tex @@ -1,31 +1,85 @@ \documentclass[j-spec.tex]{subfiles} \begin{document} -%\setcounter{tocdepth}{3} +\pagestyle{plain} +\sloppy \tableofcontents -\section{Специализация: данные и функции} +\section{Специализация: ООП} \subsection{В предыдущем разделе} Будет рассмотрен базовый функционал языка, то есть основная встроенная функциональность, такая как математические операторы, условия, циклы, бинарные операторы. Далее способы хранения и представления данных в Java, и в конце способы манипуляции данными, то есть функции (в терминах языка называющиеся методами). \subsection{В этом разделе} Разберём такие основополагающих в Java вещи, как классы и объекты, а также с тем, как применять на практике основные принципы ООП: наследование, полиморфизм и инкапсуляцию. Дополнительно рассмотрим устройство памяти в джава. \begin{itemize} -\item \nom{класс}{- } -\item \nom{объект}{- } -\item \nom{статика}{- } -\item \nom{стек}{- } -\item \nom{куча}{- } -\item \nom{сборщик мусора}{- } -\item \nom{конструктор}{- } -\item \nom{вложенный класс}{- } -\item \nom{внутренний класс}{- } -\item \nom{инкапсуляция}{- } -\item \nom{наследование}{- } -\item \nom{полиморфизм }{- } +\item \nom{Класс}{определяет форму и сущность объекта и является логической конструкцией, на основе которой построен весь язык Java. Определяет новый тип данных}; +\item \nom{Объект}{конкретный экземпляр класса, созданный в программе}; +\item \nom{Статика}{(статический контекст) - }; +\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{lstlisting}[language=Java,style=JCodeStyle] +\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 { @@ -35,12 +89,25 @@ public class Cat { } \end{lstlisting} +\begin{frm} \excl +Для новичка важно не запутаться, класс кота мы описали в отдельном файле, а создавать объекты и совершать манипуляции следует в основном классе программы, не может же кот назначить имя сам себе. +\end{frm} + +Мы рассказали программе, что такое коты, теперь если мы хотим создать в нашем приложении конкретного кота, следует воспользоваться оператором \code{new Cat();} в основном классе программы. Более подробно разберём, что происходит в этой строке, чуть позже, пока же нам достаточно знать, что мы создали объект типа \code{Cat} (экземпляр класса \code{Cat}), и запомнить эту конструкцию. Для того чтобы с ним (экземпляром) работать, можем положить его в переменную, которой дать идентификатор \code{cat1}. + \begin{lstlisting}[language=Java,style=JCodeStyle] Сat cat0; 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; @@ -58,32 +125,127 @@ public class Main{ 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); + 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{0.42} + \fontsize{6}{1}\selectfont + \input{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 = 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); + Сat 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{frm}\info + Множественные ссылки на один и тот же объект в памяти довольно легко себе представить как ярлыки для запуска одной и той же программы на рабочем столе и в меню быстрого запуска. Или если на один и тот же шкафчик в раздевалке наклеить два номера - сам шкафчик можно будет найти по двум ссылкам на него. +\end{frm} + +\subsubsection{Методы} +Ранее было сказано о том, что в языке Java любая программа состоит из классов и функций, которые могут описываться только внутри них. Именно поэтому все функции в языке Java являются методами. А метод - это функция, являющаяся частью некоторого класса, которая может выполнять операции над данными этого класса. + +\begin{frm} \info + Метод - это функция, принадлежащая классу +\end{frm} + +Метод для своей работы может использовать поля объекта и/или класса, в котором определен, напрямую, без необходимости передавать их во входных параметрах. Это похоже на использование глобальных переменных в функциях, но в отличие от глобальных переменных, метод может получать прямой доступ только к членам класса. Самые простые методы работают с данными объектов. Методы чаще всего формируют API классов, то есть способ взаимодействия с классами, интерфейс. Место методов во взаимодействии классов и объектов показано на рис. \hrf{pic:class-obj-nostatic}. + +\begin{figure}[H] + \centering + \def\svgscale{0.42} + \fontsize{6}{1}\selectfont + \input{pics/jc-03-class-obj-nostatic.svg} + \caption{Логическая структура отношения класс-объект} + \label{pic:class-obj-nostatic} +\end{figure} + +Лайвкод 03-метод & Вернёмся к примеру с котиками. Все мы знаем, что котики умеют урчать, мяукать и смешно прыгать. В целях демонстрации мы в описании этих действий просто будем делать разные выводы в консоль, хотя мы и можем научить нашего котика выбирать минимальное значение из массива, но это было бы неожиданно. Итак опишем метод например подать голос и прыгать. \\ \hline + +Лайвкод 03-метод-вызов & Обращение к методам выглядит очень похожим на стандартный способом, через точку, как к полям. Теперь когда мы хотим позвать нашего котика, он нам скажет, мяу, я имя котика, а если мы решили что котику надо прыгать, он решит, прилично-ли это - прыгать в его возрасте. Как видно, барсик замечательно прыгает, а мурзик от прыжков воздержался, хотя попрыгать мы попросили их обоих \\ \hline + +\subsubsection{Задание для самопроверки} +\begin{enumerate} + \item Что такое класс? + \item Что такое поле класса? + \item На какие три этапа делится создание объекта? +\end{enumerate} + +\subsection{Стек и куча} +\subsection{Сборка мусора} +\subsection{Конструкторы} +\subsection{Инкапсуляция} +\subsection{Наследование} +\subsection{Полиморфизм} + + \begin{verbatim} Cat1 named: Murzik is Black has age: 6 Cat2 named: Murzik is Black has age: 6 @@ -159,6 +321,7 @@ public class Cat { ключевое слово this в Java используется только в составе экземпляра класса. Но неявно ключевое слово this передается во все методы, кроме статических (поэтому this часто называют неявным параметром) и может быть использовано для обращения к объекту, вызвавшему метод. +\newpage \printnomenclature[40mm] \end{document} diff --git a/pics/jc-03-class-obj-fields.svg b/pics/jc-03-class-obj-fields.svg new file mode 100644 index 0000000..b688795 --- /dev/null +++ b/pics/jc-03-class-obj-fields.svg @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + class + fields + + object1 + field values + object2 + field values + + + + + + diff --git a/pics/jc-03-class-obj-full.svg b/pics/jc-03-class-obj-full.svg new file mode 100644 index 0000000..e2173c1 --- /dev/null +++ b/pics/jc-03-class-obj-full.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + class + fields + methods + static fields + static methods + static field values + + object1 + field values + object2 + field values + + + + + + diff --git a/pics/jc-03-class-obj-nostatic.svg b/pics/jc-03-class-obj-nostatic.svg new file mode 100644 index 0000000..7e63490 --- /dev/null +++ b/pics/jc-03-class-obj-nostatic.svg @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + class + fields + methods + + object1 + field values + object2 + field values + + + + + + diff --git a/scenarios/.#jtc3-03b.tex b/scenarios/.#jtc3-03b.tex new file mode 100644 index 0000000..00c460e --- /dev/null +++ b/scenarios/.#jtc3-03b.tex @@ -0,0 +1 @@ +Ovchinnikov_II@OVCHINNIKOV_II.21588:1669277770 \ No newline at end of file