deb try fail
This commit is contained in:
parent
f4551ea09f
commit
ab2d8730ca
BIN
build/j-spec.pdf
BIN
build/j-spec.pdf
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
j-spec.tex
10
j-spec.tex
|
@ -23,12 +23,14 @@
|
|||
\newpage
|
||||
\subfile{jtc2-02a}
|
||||
\newpage
|
||||
\subfile{jtd6-11a}
|
||||
\subfile{jtc3-03a}
|
||||
%\newpage
|
||||
%\subfile{jtd6-11a}
|
||||
|
||||
\section{Специализация: ООП}
|
||||
%\section{Специализация: ООП}
|
||||
|
||||
\section{Специализация: Тонкости работы}
|
||||
Файловая система и представление данных; Пакеты \code{java.io}, \code{java.nio}, \code{String}, \code{StringBuilder}, string pool, ?JSON/XML?
|
||||
%\section{Специализация: Тонкости работы}
|
||||
%Файловая система и представление данных; Пакеты \code{java.io}, \code{java.nio}, \code{String}, \code{StringBuilder}, string pool, ?JSON/XML?
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
|
|
72
jc4-04.tex
72
jc4-04.tex
|
@ -1,72 +0,0 @@
|
|||
% 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();
|
||||
% }
|
||||
% }
|
|
@ -401,7 +401,7 @@
|
|||
Также существует понятие \textit{инициализации} -- это когда объединяются на одной строке объявление и присваивание.\end{frm}
|
||||
|
||||
\subsubsection{Преобразование типов}
|
||||
Java - это язык со строгой статической типизацией, но преобразование типов в ней всё равно есть. Простыми словами, преобразование типов -- это когда компилятор видит, что типы переменных по разные стороны присваивания разные, начинает разрешать это противоречие, успешно или нет. Преобразование типов бывает явное и неявное. Неявное преобразование типов происходит когда компилятор в состоянии сам преобразовать типы, явное, когда ему нужна помощь.
|
||||
Java -- это язык со строгой статической типизацией, но преобразование типов в ней всё равно есть. Простыми словами, преобразование типов -- это когда компилятор видит, что типы переменных по разные стороны присваивания разные, начинает разрешать это противоречие, успешно или нет. Преобразование типов бывает явное и неявное. Неявное преобразование типов происходит когда компилятор в состоянии сам преобразовать типы, явное, когда ему нужна помощь.
|
||||
|
||||
\begin{frm}
|
||||
\info В разговоре или в сообществах можно услышать или прочитать термины тайпкастинг, кастинг, каст, кастануть, и другие производные от английского typecasting.
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
\begin{itemize}
|
||||
\item \nom{Класс}{определяет форму и сущность объекта и является логической конструкцией, на основе которой построен весь язык Java. Определяет новый тип данных};
|
||||
\item \nom{Объект}{конкретный экземпляр класса, созданный в программе};
|
||||
\item \nom{Статика}{(статический контекст) static - (от греч. неподвижный) — раздел механики, в котором изучаются условия равновесия механических систем под действием приложенных к ним сил и возникших моментов. В языке программирования Java - принадлежность поля и его значения не объекту, а классу, и, как следствие, доступность такого поля и его значения в единственном экземпляре всем объектам класса.};
|
||||
\item \nom{Статика}{(статический контекст) static -- (от греч. неподвижный) -- раздел механики, в котором изучаются условия равновесия механических систем под действием приложенных к ним сил и возникших моментов. В языке программирования Java -- принадлежность поля и его значения не объекту, а классу, и, как следствие, доступность такого поля и его значения в единственном экземпляре всем объектам класса.};
|
||||
\item \nom{Стек}{структура данных, работающая по принципу LIFO (last in, first out) или FILO (first in, last out). Стековая память отвечает за хранение ссылок на объекты кучи и за хранение типов значений (также известных в Java как примитивные типы), которые содержат само значение, а не ссылку на объект из кучи.};
|
||||
\item \nom{Куча}{адресуемое пространство оперативной памяти компьютера. Куча содержит все объекты, созданные в вашем приложении, независимо от того, какой поток создал объект.};
|
||||
\item \nom{Сборщик мусора}{специализированная подпрограмма, очищающая память от неиспользуемых объектов.};
|
||||
|
@ -157,7 +157,7 @@ Cat2 named: Murzik is Black has age: 6
|
|||
\item Сначала создается переменная, имеющая интересующий нас тип, в неё возможно записать ссылку на объект;
|
||||
\item затем необходимо выделить память под объект;
|
||||
\item создать и положить объект в выделенную часть памяти;
|
||||
\item и сохранить ссылку на этот объект в памяти - в нашу переменную.
|
||||
\item и сохранить ссылку на этот объект в памяти -- в переменную.
|
||||
\end{itemize}
|
||||
|
||||
Для непосредственного создания объекта применяется оператор \code{new}, который динамически резервирует память под объект и возвращает ссылку на него, в общих чертах эта ссылка представляет собой адрес объекта в памяти, зарезервированной оператором \code{new}.
|
||||
|
@ -176,7 +176,7 @@ Cat2 named: Murzik is Black has age: 6
|
|||
[квалификаторы] ИмяКласса имяПеременной = \textbf{\code{new}} ИмяКласса();
|
||||
\end{frm}
|
||||
|
||||
Оператор \code{new} динамически выделяет память для нового объекта, общая форма применения этого оператора имеет вид как на врезке выше, но на самом деле справа - не имя класса, конструкция ИмяКласса() в правой части выполняет вызов конструктора данного класса, который подготавливает вновь создаваемый объект к работе.
|
||||
Оператор \code{new} динамически выделяет память для нового объекта, общая форма применения этого оператора имеет вид как на врезке выше, но на самом деле справа -- не имя класса, конструкция ИмяКласса() в правой части выполняет вызов конструктора данного класса, который подготавливает вновь создаваемый объект к работе.
|
||||
|
||||
Именно от количества применений оператора \code{new} будет зависеть, сколько именно объектов будет создано в программе.
|
||||
|
||||
|
@ -210,16 +210,16 @@ Cat2 named: Murzik is Black has age: 6
|
|||
\end{verbatim}
|
||||
|
||||
\begin{frm}\info
|
||||
Множественные ссылки на один и тот же объект в памяти довольно легко себе представить как ярлыки для запуска одной и той же программы на рабочем столе и в меню быстрого запуска. Или если на один и тот же шкафчик в раздевалке наклеить два номера - сам шкафчик можно будет найти по двум ссылкам на него.
|
||||
Множественные ссылки на один и тот же объект в памяти довольно легко себе представить как ярлыки для запуска одной и той же программы на рабочем столе и в меню быстрого запуска. Или если на один и тот же шкафчик в раздевалке наклеить два номера -- сам шкафчик можно будет найти по двум ссылкам на него.
|
||||
\end{frm}
|
||||
|
||||
Важно всегда перепроверять, какие объекты созданы, а какие имеют множественные ссылки.
|
||||
|
||||
\subsubsection{Методы}
|
||||
Ранее было сказано о том, что в языке Java любая программа состоит из классов и функций, которые могут описываться только внутри них. Именно поэтому все функции в языке Java являются методами. А метод - это функция, являющаяся частью некоторого класса, которая может выполнять операции над данными этого класса.
|
||||
Ранее было сказано о том, что в языке Java любая программа состоит из классов и функций, которые могут описываться только внутри них. Именно поэтому все функции в языке Java являются методами. А метод -- это функция, являющаяся частью некоторого класса, которая может выполнять операции над данными этого класса.
|
||||
|
||||
\begin{frm} \info
|
||||
Метод - это функция, принадлежащая классу
|
||||
Метод -- это функция, принадлежащая классу
|
||||
\end{frm}
|
||||
|
||||
Метод для своей работы может использовать поля объекта и/или класса, в котором определен, напрямую, без необходимости передавать их во входных параметрах. Это похоже на использование глобальных переменных в функциях, но в отличие от глобальных переменных, метод может получать прямой доступ только к членам класса. Самые простые методы работают с данными объектов. Методы чаще всего формируют API классов, то есть способ взаимодействия с классами, интерфейс. Место методов во взаимодействии классов и объектов показано на рис. \hrf{pic:class-obj-nostatic}.
|
||||
|
@ -330,7 +330,7 @@ public class Cat {
|
|||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Помимо того, что статические поля - это полезный инструмент создания общих свойств это ещ§ и опасный инструмент создания общих свойств. Так, например, мы знаем, что у котов четыре лапы, а не 6 и не 8. Не создавая никакого барсика будет понятно, что у кота - 4 лапы. Это полезное поведение.
|
||||
Помимо того, что статические поля -- это полезный инструмент создания общих свойств это ещ§ и опасный инструмент создания общих свойств. Так, например, мы знаем, что у котов четыре лапы, а не 6 и не 8. Не создавая никакого барсика будет понятно, что у кота -- 4 лапы. Это полезное поведение.
|
||||
|
||||
лайвкод 03-статическое-поле-ошибка Посмотрим на опасность. Мы видим, что у каждого кота есть имя, и помним, что коты хранят значение своего имени каждый сам у себя. А знают экземпляры о названии поля потому что знают, какого класса они экземпляры. Но что если мы по невнимательности добавим свойство статичности к имени кота?
|
||||
|
||||
|
@ -390,7 +390,7 @@ public class Cat {
|
|||
\begin{itemize}
|
||||
\item Young Generation — область где размещаются недавно созданные объекты. Когда она заполняется, происходит быстрая сборка мусора;
|
||||
\item Old (Tenured) Generation — здесь хранятся долгоживущие объекты. Когда объекты из Young Generation достигают определенного порога «возраста», они перемещаются в Old Generation;
|
||||
\item Permanent Generation — эта область содержит метаинформацию о классах и методах приложения, но начиная с Java 8 данная область памяти была упразднена. В Java 8 Permanent Generation заменён на Metaspace - его динамически изменяемый по размеру аналог. Именно здесь находятся статические поля.
|
||||
\item Permanent Generation — эта область содержит метаинформацию о классах и методах приложения, но начиная с Java 8 данная область памяти была упразднена. В Java 8 Permanent Generation заменён на Metaspace -- его динамически изменяемый по размеру аналог. Именно здесь находятся статические поля.
|
||||
\end{itemize}
|
||||
Особенности кучи:
|
||||
\begin{itemize}
|
||||
|
@ -416,7 +416,7 @@ public class Cat {
|
|||
|
||||
Поскольку это довольно сложный процесс и может повлиять на производительность всего приложения, он реализован весьма разумно. Для этого используется так называемый процесс «Mark and Sweep» (отмечай и подметай). Java анализирует переменные из стека и «отмечает» все объекты, которые необходимо поддерживать в рабочем состоянии. Затем все неиспользуемые объекты очищаются. Фактически, чем больше мусора и чем меньше объектов помечены как живые, тем быстрее идет процесс. Чтобы сделать это еще более оптимизированным, память кучи состоит из нескольких частей.
|
||||
\begin{enumerate}
|
||||
\item Молодое поколение -- Все новые объекты начинаются с молодого поколения. Как только они выделены в коде Java, они попадают в этот подраздел, называемый \textbf{eden space}. В конце концов пространство эдема заполняется объектами. На этом этапе происходит незначительная сборка мусора, так называемая minor collection. Некоторые объекты (те, на которые есть ссылки) помечаются, а некоторые (те, на которые нет ссылок) - нет. Те, которые были отмечены, затем переходят в другой подраздел молодого поколения под названием пространство выживших (само пространство выживших разделено на две части). Те, которые остались немаркированными, удаляются автоматической сборкой мусора.
|
||||
\item Молодое поколение -- Все новые объекты начинаются с молодого поколения. Как только они выделены в коде Java, они попадают в этот подраздел, называемый \textbf{eden space}. В конце концов пространство эдема заполняется объектами. На этом этапе происходит незначительная сборка мусора, так называемая minor collection. Некоторые объекты (те, на которые есть ссылки) помечаются, а некоторые (те, на которые нет ссылок) -- нет. Те, которые были отмечены, затем переходят в другой подраздел молодого поколения под названием пространство выживших (само пространство выживших разделено на две части). Те, которые остались немаркированными, удаляются автоматической сборкой мусора.
|
||||
\item Выжившее поколение -- Так будет продолжаться до тех пор, пока пространство eden снова не заполнится; на этом этапе начинается новый цикл. События minor collection повторяются, но в этом цикле все отмеченные объекты, которые выживают как из пространства eden, так и из S0, фактически попадают во вторую часть пространства survivor, называемую S1.
|
||||
\item Третье поколение -- Любые объекты, попадающие в пространство выживших, помечаются счетчиком возраста. Алгоритм проверяет этот счётчик, чтобы увидеть, соответствует ли он пороговому значению для перехода в старое поколение. Главная мысль в том, что объекты не обязательно переходят из S0 в S1 пространства выживших. На самом деле, они просто чередуются с тем, куда они переключаются при каждой minor сборке мусора.
|
||||
|
||||
|
@ -436,7 +436,7 @@ public class Cat {
|
|||
\begin{frm}\info Следует отметить, что, поскольку этот GC является параллельным, вызов явной сборки мусора, такой как использование System.gc() во время работы параллельного процесса, приведет к сбою или прерыванию параллельного режима;
|
||||
\end{frm}
|
||||
\item Сборщик мусора G1. Сборщик мусора G1 (Garbage First) предназначен для приложений, работающих на многопроцессорных компьютерах с большим объемом памяти. Он доступен с обновления 4 JDK7 и в более поздних версиях. Сборщик G1 заменит сборщик CMS, поскольку он более эффективен;
|
||||
\item Z сборщик мусора. ZGC (Z Garbage Collector) - это масштабируемый сборщик мусора с низкой задержкой, который дебютировал в Java 11 в качестве экспериментального варианта для Linux. JDK 14 представил ZGC под операционными системами Windows и macOS. ZGC получил статус production начиная с Java 15.
|
||||
\item Z сборщик мусора. ZGC (Z Garbage Collector) -- это масштабируемый сборщик мусора с низкой задержкой, который дебютировал в Java 11 в качестве экспериментального варианта для Linux. JDK 14 представил ZGC под операционными системами Windows и macOS. ZGC получил статус production начиная с Java 15.
|
||||
\end{enumerate}
|
||||
|
||||
Итоги рассмотрения устройства памяти
|
||||
|
@ -457,7 +457,7 @@ public class Cat {
|
|||
|
||||
\subsection{Конструкторы}
|
||||
\subsubsection{Контроль над созданием объекта}
|
||||
Чтобы создать объект мы тратим одну строку кода \code{Cat cat1 = new Cat();} поля этого объекта заполнятся автоматически значениями по-умолчанию (числовые - 0, логические - \code{false}, ссылочные - \code{null}). Часто нужно при создании дать коту какое-то имя, указать его возраст и цвет, поэтому пишем ещё три строки кода.
|
||||
Чтобы создать объект мы тратим одну строку кода \code{Cat cat1 = new Cat();} поля этого объекта заполнятся автоматически значениями по-умолчанию (числовые -- 0, логические -- \code{false}, ссылочные -- \code{null}). Часто нужно при создании дать коту какое-то имя, указать его возраст и цвет, поэтому пишем ещё три строки кода.
|
||||
|
||||
\begin{frm} \excl В таком подходе есть несколько недостатков:
|
||||
\begin{enumerate}
|
||||
|
@ -468,7 +468,7 @@ public class Cat {
|
|||
|
||||
Было бы неплохо иметь возможность сразу, при создании объекта указывать значения его полей. Для инициализации объектов при создании в Java предназначены конструкторы.
|
||||
|
||||
\begin{frm} \info Конструктор - это частный случай метода в том смысле, что он тоже выполняет какие-то действия. Имя конструктора обязательно должно совпадать с именем класса, возвращаемое значение не пишется.
|
||||
\begin{frm} \info Конструктор -- это частный случай метода в том смысле, что он тоже выполняет какие-то действия. Имя конструктора обязательно должно совпадать с именем класса, возвращаемое значение не пишется.
|
||||
\end{frm}
|
||||
|
||||
Если создать конструктор класса Cat, как показано в листинге \hrf{lst:construct-bad}, он автоматически будет вызываться при создании объекта. Теперь, при создании объектов класса Cat, все коты будут иметь одинаковые имена, цвет и возраст (это будут белые двухлетние Барсики).
|
||||
|
@ -552,7 +552,7 @@ public class Cat {
|
|||
|
||||
Ключевое слово \code{this} сошлётся на вызвавший объект, в результате чего (в листинге \hrf{lst:constr-this})имя котика через конструктор будет установлено создаваемому объекту. Таким образом, здесь \code{this} позволяет не вводить новые переменные для обозначения одного и того же, что позволяет сделать код менее перегруженным дополнительными переменными.
|
||||
|
||||
Второй случай частого использования \code{this} с конструкторами - вызов одного конструктора из другого. это может пригодиться когда в классе описано несколько конструкторов и не хочется в новом конструкторе переписывать код инициализации, приведенный в конструкторе ранее\footnote{один из базовых принципов программирования - DRY (от англ dry - чистый, сухой, акроним don't repeat yourself) - не повторяйся. Его антагонист WET (от англ wet - влажный, акроним write everything twice) - пиши всё дважды.}. В листинге \hrf{lst:constr-this} вызывается обычный конструктор с тремя параметрами, который принимает имя цвет и возраст, но, допустим, когда котята рождаются возраст им задавать смысла нет, поэтому, может пригодиться и конструктор просто с именем и цветом, а зачем писать присваивание имени и цвета несколько раз, если можно вызвать соответствующий конструктор?
|
||||
Второй случай частого использования \code{this} с конструкторами -- вызов одного конструктора из другого. это может пригодиться когда в классе описано несколько конструкторов и не хочется в новом конструкторе переписывать код инициализации, приведенный в конструкторе ранее\footnote{один из базовых принципов программирования -- DRY (от англ dry -- чистый, сухой, акроним don't repeat yourself) -- не повторяйся. Его антагонист WET (от англ wet -- влажный, акроним write everything twice) -- пиши всё дважды.}. В листинге \hrf{lst:constr-this} вызывается обычный конструктор с тремя параметрами, который принимает имя цвет и возраст, но, допустим, когда котята рождаются возраст им задавать смысла нет, поэтому, может пригодиться и конструктор просто с именем и цветом, а зачем писать присваивание имени и цвета несколько раз, если можно вызвать соответствующий конструктор?
|
||||
|
||||
\begin{lstlisting}[language=Java,style=JCodeStyle,label={lst:constr-this},caption={Использование ключевого слова \code{this} для параметров}]
|
||||
public class Cat {
|
||||
|
@ -579,7 +579,7 @@ public class Cat {
|
|||
\begin{frm} \info Ключевое слово \code{this} в Java используется только в составе экземпляра класса. Но неявно ключевое слово \code{this} передается во все методы, кроме статических (поэтому \code{this} часто называют неявным параметром) и может быть использовано для обращения к объекту, вызвавшему метод.
|
||||
\end{frm}
|
||||
|
||||
Существует ещё один вид конструктора - это \textbf{конструктор копирования}. Чтобы создать конструктор копирования, возможно объявить конструктор, который принимает объект того же типа, в нашем случае котика, в качестве параметра, а в самом конструкторе аналогично конструктору, заполняющему все параметры, заполнить каждое поле входного объекта в новый экземпляр.
|
||||
Существует ещё один вид конструктора -- это \textbf{конструктор копирования}. Чтобы создать конструктор копирования, возможно объявить конструктор, который принимает объект того же типа, в нашем случае котика, в качестве параметра, а в самом конструкторе аналогично конструктору, заполняющему все параметры, заполнить каждое поле входного объекта в новый экземпляр.
|
||||
|
||||
\begin{lstlisting}[language=Java,style=JCodeStyle]
|
||||
public Cat (Cat cat) {
|
||||
|
@ -604,10 +604,10 @@ public Cat (Cat cat) {
|
|||
Инкапсуляция связывает данные с манипулирующим ими кодом и позволяет управлять доступом к членам класса из отдельных частей программы, предоставляя доступ только с помощью определенного ряда методов, что позволяет предотвратить злоупотребление этими данными. То есть класс должен представлять собой «черный ящик», которым возможно пользоваться, но его внутренний механизм защищен от повреждений.
|
||||
|
||||
\begin{frm}\info
|
||||
\textbf{Инкапсуляция} - (англ. encapsulation, от лат. in capsula) — в информатике, процесс разделения элементов абстракций, определяющих ее структуру (данные) и поведение (методы); инкапсуляция предназначена для изоляции контрактных обязательств абстракции (протокол/интерфейс) от их реализации.
|
||||
\textbf{Инкапсуляция} -- (англ. encapsulation, от лат. in capsula) -- в информатике, процесс разделения элементов абстракций, определяющих ее структуру (данные) и поведение (методы); инкапсуляция предназначена для изоляции контрактных обязательств абстракции (протокол/интерфейс) от их реализации.
|
||||
\end{frm}
|
||||
|
||||
В Java в роли чёрного ящика выступает класс. Класс содержит в себе и данные (поля класса), и действия (методы класса) для работы с этими данными. Все члены класса в языке Java - поля и методы - имеют модификаторы доступа. Ранее уже было описан модификатор \code{public}, означающий доступность отовсюду, обычно используется для методов.
|
||||
В Java в роли чёрного ящика выступает класс. Класс содержит в себе и данные (поля класса), и действия (методы класса) для работы с этими данными. Все члены класса в языке Java -- поля и методы -- имеют модификаторы доступа. Ранее уже было описан модификатор \code{public}, означающий доступность отовсюду, обычно используется для методов.
|
||||
|
||||
\begin{frm} \info Модификаторы доступа позволяют задать допустимую область видимости для членов класса, то есть контекст, в котором можно употреблять данную переменную или метод.
|
||||
\end{frm}
|
||||
|
@ -662,12 +662,12 @@ public class Cat {
|
|||
|
||||
Важно, что создавая для класса геттеры и сеттеры не только появляется возможность дополнять установке и возвращению значений полей дополнительную логику, но и возможность регулировать доступ к полям. Например, если в программе нужно запретить менять котикам окрас, то для класса просто не пишется соответствующий сеттер.
|
||||
|
||||
Внимательно осмотрев класс кота возможно прийти к выводу, что хранить возраст котов очень неудобно, потому что каждый год нужно будет обновлять это значение для каждого объекта кота в программе, а это может оказаться утомительно. Выходом может оказаться хранение не возраста, а неизменяемого параметра - даты рождения и подсчёт возраста каждый раз, когда его запрашивают, ведь человеку, который запрашивает возраст кота, не интересно, каким образом получено значение, прочитано из поля или вычислено, ему важен конечный результат. Это и есть инкапсуляция, сокрытие реализации.
|
||||
Внимательно осмотрев класс кота возможно прийти к выводу, что хранить возраст котов очень неудобно, потому что каждый год нужно будет обновлять это значение для каждого объекта кота в программе, а это может оказаться утомительно. Выходом может оказаться хранение не возраста, а неизменяемого параметра -- даты рождения и подсчёт возраста каждый раз, когда его запрашивают, ведь человеку, который запрашивает возраст кота, не интересно, каким образом получено значение, прочитано из поля или вычислено, ему важен конечный результат. Это и есть инкапсуляция, сокрытие реализации.
|
||||
|
||||
\subsubsection{Задания для самопроверки}
|
||||
\begin{enumerate}
|
||||
\item Перечислите модификаторы доступа
|
||||
\item Инкапсуляция - это
|
||||
\item Инкапсуляция -- это
|
||||
\begin{enumerate}
|
||||
\item архивирование проекта
|
||||
\item сокрытие информации о классе
|
||||
|
@ -677,7 +677,7 @@ public class Cat {
|
|||
|
||||
\subsection{Наследование}
|
||||
\subsubsection{Проблема}
|
||||
Второй кит ООП после инкапсуляции - наследование.
|
||||
Второй кит ООП после инкапсуляции -- наследование.
|
||||
|
||||
Представим, что есть необходимость создать помимо класса котиков, класс собачек. Данный класс будет выглядеть очень похожим образом, только он будет не мяукать, а гавкать, и заменим обоим животным прыжок на простое перемещение на лапках.
|
||||
|
||||
|
@ -780,7 +780,7 @@ public class Dog {
|
|||
\begin{frm} \info Наследование (англ. inheritance) — концепция объектно-ориентированного программирования, согласно которой абстрактный тип данных может наследовать данные и функциональность некоторого существующего типа, способствуя повторному использованию компонентов программного обеспечения.
|
||||
\end{frm}
|
||||
|
||||
Наследование в Java реализуется ключевым словом \code{extends} (англ. - расширять). И кот и пёс являются животными, у всех описываемых в программе животных есть имя, возраст, окрас, все описываемые животные могут бегать, прыгать, и откликаться на имя. Создав так называемый \textbf{родительский класс}, или суперкласс (листинг \hrf{lst:animal-fields}), и поместив в него поля, геттеры и сеттеры, стало возможным убрать поля, геттеры и сеттеры из кота и пса. Если полей много, лаконичность описания родственных классов может быть весьма ощутимой.
|
||||
Наследование в Java реализуется ключевым словом \code{extends} (англ. -- расширять). И кот и пёс являются животными, у всех описываемых в программе животных есть имя, возраст, окрас, все описываемые животные могут бегать, прыгать, и откликаться на имя. Создав так называемый \textbf{родительский класс}, или суперкласс (листинг \hrf{lst:animal-fields}), и поместив в него поля, геттеры и сеттеры, стало возможным убрать поля, геттеры и сеттеры из кота и пса. Если полей много, лаконичность описания родственных классов может быть весьма ощутимой.
|
||||
|
||||
\begin{lstlisting}[language=Java,style=JCodeStyle,label={lst:animal-fields},caption={Класс животного}]
|
||||
public class Animal {
|
||||
|
@ -859,9 +859,9 @@ public class Cat extends Animal {
|
|||
|
||||
То есть, к членам данных и методам класса можно применять следующие модификаторы доступа
|
||||
\begin{itemize}
|
||||
\item \code{private} - содержимое класса доступно только из методов данного класса;
|
||||
\item \code{public} - есть доступ фактически отовсюду;
|
||||
\item default (по-умолчанию) - содержимое класса доступно из любого места пакета, в котором этот класс находится;
|
||||
\item \code{private} -- содержимое класса доступно только из методов данного класса;
|
||||
\item \code{public} -- есть доступ фактически отовсюду;
|
||||
\item default (по-умолчанию) -- содержимое класса доступно из любого места пакета, в котором этот класс находится;
|
||||
\item \code{protected} (защищенный доступ) содержимое доступно также как с модификатором по-умолчанию, но ещё и для классов-наследников.
|
||||
|
||||
\end{itemize}
|
||||
|
@ -875,12 +875,12 @@ public class Cat extends Animal {
|
|||
То есть верным вариантом в листинге \hrf{lst:animal-fields} будет применение модификатора \code{protected}.
|
||||
|
||||
\subsubsection{Конструкторы в наследовании}
|
||||
\begin{frm} \excl Несмотря на то, что конструктор - это частный случай метода, если перенести одинаковые конструкторы кота и пса в общий класс животного, программа снова перестанет работать, потому что важно учитывать механику вызова конструкторов при наследовании.
|
||||
\begin{frm} \excl Несмотря на то, что конструктор -- это частный случай метода, если перенести одинаковые конструкторы кота и пса в общий класс животного, программа снова перестанет работать, потому что важно учитывать механику вызова конструкторов при наследовании.
|
||||
\end{frm}
|
||||
|
||||
Важно запомнить, что при создании любого объекта в первую очередь вызывается конструктор его базового (родительского) класса, а только потом — конструктор самого класса, объект которого мы создаем. То есть при создании объекта \code{Cat} сначала отработает конструктор класса \code{Animal}, а только потом конструктор \code{Cat}. Но, поскольку конструктор по-умолчанию в нашем случае перестал создаваться, а других может быть бесконечно много, это создало неопределённость, которую программа разрешить не может.
|
||||
|
||||
При описании класса, можно явно вызвать конструктор базового класса в конструкторе класса-потомка. Базовый класс еще называют «суперклассом», поэтому в Java для его обозначения используется ключевое слово \code{super}. Здесь такое же ограничение, как и при вызове конструкторов данного класса (через \code{this}) - вызов такого конструктора может быть только один и быть только первой строкой. Таким образом, код, для всех животных в программе будет выглядеть следующим образом:
|
||||
При описании класса, можно явно вызвать конструктор базового класса в конструкторе класса-потомка. Базовый класс еще называют «суперклассом», поэтому в Java для его обозначения используется ключевое слово \code{super}. Здесь такое же ограничение, как и при вызове конструкторов данного класса (через \code{this}) -- вызов такого конструктора может быть только один и быть только первой строкой. Таким образом, код, для всех животных в программе будет выглядеть следующим образом:
|
||||
|
||||
\begin{multicols}{2}
|
||||
\begin{lstlisting}[language=Java,style=JCodeStyle,label={lst:animal-full},caption={Класс животного}]
|
||||
|
@ -975,7 +975,7 @@ public class Bird extends Animal {
|
|||
\begin{frm} \excl Множественное наследование запрещено! Для каждого создаваемого подкласса можно указать только один суперкласс. В Java не поддерживается множественное наследование, то есть наследование одного класса от нескольких суперклассов. Зато возможно каскадное наследование, то есть класс-наследник вполне может быть чьим-то родителем.
|
||||
\end{frm}
|
||||
|
||||
Если класс-родитель не указан, таковым считается класс \code{Object}. Таким образом можно сделать вывод о том, что любой класс в джава так или иначе - наследник \code{Object} и, соответственно, всех его свойств и методов. Объект подкласса представляет объект суперкласса, выражаясь проще, возможно ко всем котикам обращаться через общее название Животное, и ко всем объектам в программе возможно обратиться через класс \code{Object}. Поэтому в программе не будет ошибкой написать подобный код:
|
||||
Если класс-родитель не указан, таковым считается класс \code{Object}. Таким образом можно сделать вывод о том, что любой класс в джава так или иначе -- наследник \code{Object} и, соответственно, всех его свойств и методов. Объект подкласса представляет объект суперкласса, выражаясь проще, возможно ко всем котикам обращаться через общее название Животное, и ко всем объектам в программе возможно обратиться через класс \code{Object}. Поэтому в программе не будет ошибкой написать подобный код:
|
||||
\begin{lstlisting}[language=Java,style=JCodeStyle,label={lst:obj},caption={}]
|
||||
Object animal = new Animal("Cat", "Black", 3);
|
||||
Object cat = new Cat("Murka", "Black", 4);
|
||||
|
@ -1022,7 +1022,7 @@ if (cat instanceof Dog) {
|
|||
|
||||
Абстрактный класс — это написанная максимально широкими мазками, приблизительная «заготовка» для группы будущих классов. Эту заготовку нельзя использовать в чистом виде — слишком «сырая». Но она описывает некое общее состояние и поведение, которым будут обладать будущие классы — наследники абстрактного класса.
|
||||
|
||||
Абстрактными могут быть не только классы, но и методы. \textbf{Абстрактный метод} - это метод без реализации. Все животные в примерах выше умеют издавать свой звук. Известно, на этапе проектирования животного, что все животные должны издавать звук, но невозможно сказать, какой именно. Поэтому, определяется, что у животного есть метод издать звук, но реализация этого метода в животном не пишется, слишком мало сведений. Поэтому, метод помечается как абстрактный.
|
||||
Абстрактными могут быть не только классы, но и методы. \textbf{Абстрактный метод} -- это метод без реализации. Все животные в примерах выше умеют издавать свой звук. Известно, на этапе проектирования животного, что все животные должны издавать звук, но невозможно сказать, какой именно. Поэтому, определяется, что у животного есть метод издать звук, но реализация этого метода в животном не пишется, слишком мало сведений. Поэтому, метод помечается как абстрактный.
|
||||
|
||||
Что будет, если программа попытается вызвать метод \code{voice()} у животного?
|
||||
|
||||
|
@ -1030,8 +1030,8 @@ if (cat instanceof Dog) {
|
|||
|
||||
\begin{frm} \info
|
||||
\begin{itemize}
|
||||
\item Абстрактный метод - это метод не содержащий реализации (объявление метода).
|
||||
\item Абстрактный класс - класс содержащий хотя бы один абстрактный метод.
|
||||
\item Абстрактный метод -- это метод не содержащий реализации (объявление метода).
|
||||
\item Абстрактный класс -- класс содержащий хотя бы один абстрактный метод.
|
||||
\item Абстрактный класс нельзя инстанциировать (создать экземпляр).
|
||||
\end{itemize}
|
||||
\end{frm}
|
||||
|
@ -1046,7 +1046,7 @@ if (cat instanceof Dog) {
|
|||
\item extends
|
||||
\item как в С++, используется двоеточие
|
||||
\end{enumerate}
|
||||
\item super - это
|
||||
\item super -- это
|
||||
\begin{enumerate}
|
||||
\item ссылка на улучшенный класс
|
||||
\item ссылка на расширенный класс
|
||||
|
@ -1134,9 +1134,9 @@ public class Cat extends Animal {
|
|||
\begin{frm} \info Полиморфизм в языках программирования и теории типов — способность функции обрабатывать данные разных типов. Выделяют параметрический полиморфизм и ad-hoc-полиморфизм.
|
||||
\end{frm}
|
||||
|
||||
Широко распространено определение полиморфизма, приписываемое Бьёрну Страуструпу: «один интерфейс — много реализаций». Полиморфизм - это гораздо более широкое понятие, чем просто переопределение методов, в эту тему завязаны разные интересные теории типов и информации, множество парадигм программирования и другое. С утилитарной точки зрения, остался ещё один вариант, который, тем не менее, не дотягивает до истинного полиморфизма.
|
||||
Широко распространено определение полиморфизма, приписываемое Бьёрну Страуструпу: «один интерфейс — много реализаций». Полиморфизм -- это гораздо более широкое понятие, чем просто переопределение методов, в эту тему завязаны разные интересные теории типов и информации, множество парадигм программирования и другое. С утилитарной точки зрения, остался ещё один вариант, который, тем не менее, не дотягивает до истинного полиморфизма.
|
||||
|
||||
\begin{frm} \info К полиморфизму также относится перегрузка методов (Overloading) - использование более одного метода с одним и тем же именем, но с разными параметрами в одном и том же классе или между суперклассом и подклассами. \end{frm}
|
||||
\begin{frm} \info К полиморфизму также относится перегрузка методов (Overloading) -- использование более одного метода с одним и тем же именем, но с разными параметрами в одном и том же классе или между суперклассом и подклассами. \end{frm}
|
||||
|
||||
Перегрузка работает также, как работала без явной привязки кода к парадигме ООП, ничего нового, но для порядка следует создать возможность животным перемещаться не только абстрактно, но и на какое-то конкретное место или на какое-то конкретное количество шагов.
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
\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();
|
||||
% }
|
||||
% }
|
|
@ -1 +0,0 @@
|
|||
Ovchinnikov_II@OVCHINNIKOV_II.21588:1669277770
|
|
@ -1,5 +1,4 @@
|
|||
\documentclass[../j-spec.tex]{subfiles}
|
||||
\usepackage{spreadtab}
|
||||
|
||||
\begin{document}
|
||||
\sloppy
|
||||
|
@ -88,7 +87,7 @@
|
|||
\item Библиотеки;
|
||||
\item Фреймворки.
|
||||
\end{enumerate}
|
||||
\item Основная единица исходного кода программы - это? (2)
|
||||
\item Основная единица исходного кода программы -- это? (2)
|
||||
\begin{enumerate}
|
||||
\item Функция;
|
||||
\item Класс;
|
||||
|
@ -336,8 +335,13 @@ javadoc -d doc_bg -sourcepath . -cp ./out ru.bg
|
|||
\end{itemize}
|
||||
\item \textbf{Задания}
|
||||
\begin{enumerate}
|
||||
\item Решить все задания (в том числе «со звёздочкой»), если они не были решены на семинаре, без ограничений по времени;
|
||||
\item Создать докер образ для формирования полной документации по проекту/
|
||||
\item [5-25 мин] Решить все задания (в том числе «со звёздочкой»), если они не были решены на семинаре, без ограничений по времени;
|
||||
|
||||
Все варианты решения приведены в тексте семинара выше
|
||||
\item [10-15 мин] Создать докер образ для формирования полной документации по проекту
|
||||
|
||||
\lstinputlisting[style=CCodeStyle,caption={docker-compose-class.yml}]{src/s01-h04-docker-compose-docs.yml}
|
||||
|
||||
\end{enumerate}
|
||||
\end{itemize}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
\end{itemize}
|
||||
\item \textbf{Вопросы и ответы:}
|
||||
\begin{enumerate}
|
||||
\item
|
||||
\item
|
||||
\end{enumerate}
|
||||
\end{itemize}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
services:
|
||||
app:
|
||||
image: bellsoft/liberica-openjdk-alpine:11.0.16.1-1
|
||||
command: javadoc -sourcepath /app/src -cp /app/out -d /app/doc -subpackages ru
|
||||
volumes:
|
||||
- ./bin:/app/out
|
||||
- ./src:/app/src
|
||||
- ./doc:/app/doc
|
|
@ -19,6 +19,7 @@
|
|||
\usepackage{booktabs}% http://ctan.org/pkg/booktabs
|
||||
\usepackage{setspace,fontspec}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{spreadtab}
|
||||
\usepackage{svg}
|
||||
|
||||
\newcommand{\tabitem}{~~\llap{\textbullet}~~}
|
||||
|
@ -60,7 +61,7 @@
|
|||
\lhead{\includegraphics[height=5mm]{logo.png}}
|
||||
% \rhead{И.И. Овчинников \\ \href{https://t.me/ivanigorevichfeed}{Telegram: ivanigorevichfeed}}
|
||||
\chead{\thepage}
|
||||
% \cfoot{\faRocket}
|
||||
\cfoot{\faRocket}
|
||||
% \rfoot{Всего слов: \wordcount}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
%% Creator: Inkscape 1.2.1 (9c6d41e4, 2022-07-14), www.inkscape.org
|
||||
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
|
||||
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
|
||||
%% Accompanies image file 'jc-02-float-struct32_svg-tex.pdf' (pdf, eps, ps)
|
||||
%%
|
||||
|
|
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
%% Creator: Inkscape 1.2.1 (9c6d41e4, 2022-07-14), www.inkscape.org
|
||||
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
|
||||
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
|
||||
%% Accompanies image file 'jc-02-float-struct_svg-tex.pdf' (pdf, eps, ps)
|
||||
%%
|
||||
|
|
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
%% Creator: Inkscape 1.2.1 (9c6d41e4, 2022-07-14), www.inkscape.org
|
||||
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
|
||||
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
|
||||
%% Accompanies image file 'jc-03-class-obj-fields_svg-tex.pdf' (pdf, eps, ps)
|
||||
%%
|
||||
|
|
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
%% Creator: Inkscape 1.2.1 (9c6d41e4, 2022-07-14), www.inkscape.org
|
||||
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
|
||||
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
|
||||
%% Accompanies image file 'jc-03-class-obj-full_svg-tex.pdf' (pdf, eps, ps)
|
||||
%%
|
||||
|
|
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
%% Creator: Inkscape 1.2.1 (9c6d41e4, 2022-07-14), www.inkscape.org
|
||||
%% Creator: Inkscape inkscape 0.92.4, www.inkscape.org
|
||||
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
|
||||
%% Accompanies image file 'jc-03-class-obj-nostatic_svg-tex.pdf' (pdf, eps, ps)
|
||||
%%
|
||||
|
|
Loading…
Reference in New Issue