diff --git a/build/j-spec.pdf b/build/j-spec.pdf index ea4ecde..e86e096 100644 Binary files a/build/j-spec.pdf and b/build/j-spec.pdf differ diff --git a/build/jc3-03a.pdf b/build/jc3-03a.pdf new file mode 100644 index 0000000..5a39fcd Binary files /dev/null and b/build/jc3-03a.pdf differ diff --git a/build/jtc4-04a.pdf b/build/jtc4-04a.pdf new file mode 100644 index 0000000..30826c7 Binary files /dev/null and b/build/jtc4-04a.pdf differ diff --git a/j-spec.tex b/j-spec.tex index d86e989..1df7e32 100644 --- a/j-spec.tex +++ b/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 diff --git a/jc4-04.tex b/jc4-04.tex deleted file mode 100644 index a598ef7..0000000 --- a/jc4-04.tex +++ /dev/null @@ -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(); -% } -% } diff --git a/jtc2-02a.tex b/jtc2-02a.tex index 0caeb97..067fcbb 100644 --- a/jtc2-02a.tex +++ b/jtc2-02a.tex @@ -401,7 +401,7 @@ Также существует понятие \textit{инициализации} -- это когда объединяются на одной строке объявление и присваивание.\end{frm} \subsubsection{Преобразование типов} -Java - это язык со строгой статической типизацией, но преобразование типов в ней всё равно есть. Простыми словами, преобразование типов -- это когда компилятор видит, что типы переменных по разные стороны присваивания разные, начинает разрешать это противоречие, успешно или нет. Преобразование типов бывает явное и неявное. Неявное преобразование типов происходит когда компилятор в состоянии сам преобразовать типы, явное, когда ему нужна помощь. +Java -- это язык со строгой статической типизацией, но преобразование типов в ней всё равно есть. Простыми словами, преобразование типов -- это когда компилятор видит, что типы переменных по разные стороны присваивания разные, начинает разрешать это противоречие, успешно или нет. Преобразование типов бывает явное и неявное. Неявное преобразование типов происходит когда компилятор в состоянии сам преобразовать типы, явное, когда ему нужна помощь. \begin{frm} \info В разговоре или в сообществах можно услышать или прочитать термины тайпкастинг, кастинг, каст, кастануть, и другие производные от английского typecasting. diff --git a/jc3-03a.tex b/jtc3-03a.tex similarity index 89% rename from jc3-03a.tex rename to jtc3-03a.tex index d1635c9..9b6d694 100644 --- a/jc3-03a.tex +++ b/jtc3-03a.tex @@ -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} Перегрузка работает также, как работала без явной привязки кода к парадигме ООП, ничего нового, но для порядка следует создать возможность животным перемещаться не только абстрактно, но и на какое-то конкретное место или на какое-то конкретное количество шагов. diff --git a/jtc4-04a.tex b/jtc4-04a.tex new file mode 100644 index 0000000..b517238 --- /dev/null +++ b/jtc4-04a.tex @@ -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(); +% } +% } diff --git a/scenarios/.#jtc3-03b.tex b/scenarios/.#jtc3-03b.tex deleted file mode 100644 index 00c460e..0000000 --- a/scenarios/.#jtc3-03b.tex +++ /dev/null @@ -1 +0,0 @@ -Ovchinnikov_II@OVCHINNIKOV_II.21588:1669277770 \ No newline at end of file diff --git a/seminars/jtc1-01c.tex b/seminars/jtc1-01c.tex index a84fc1d..0119cbb 100644 --- a/seminars/jtc1-01c.tex +++ b/seminars/jtc1-01c.tex @@ -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} diff --git a/seminars/jtc1-02c.tex b/seminars/jtc1-02c.tex index e9f1b40..2e12e31 100644 --- a/seminars/jtc1-02c.tex +++ b/seminars/jtc1-02c.tex @@ -79,7 +79,7 @@ \end{itemize} \item \textbf{Вопросы и ответы:} \begin{enumerate} - \item + \item \end{enumerate} \end{itemize} diff --git a/seminars/src/s01-hw2-docker-compose-docs.yml b/seminars/src/s01-hw2-docker-compose-docs.yml new file mode 100644 index 0000000..1835119 --- /dev/null +++ b/seminars/src/s01-hw2-docker-compose-docs.yml @@ -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 \ No newline at end of file diff --git a/settings/main-style-preamble.tex b/settings/main-style-preamble.tex index 8839f7b..cddf49d 100644 --- a/settings/main-style-preamble.tex +++ b/settings/main-style-preamble.tex @@ -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} } diff --git a/svg-inkscape/jc-01-jvm-struct_svg-tex.pdf b/svg-inkscape/jc-01-jvm-struct_svg-tex.pdf index 4a01223..e69de29 100644 Binary files a/svg-inkscape/jc-01-jvm-struct_svg-tex.pdf and b/svg-inkscape/jc-01-jvm-struct_svg-tex.pdf differ diff --git a/svg-inkscape/jc-02-float-struct32_svg-tex.pdf b/svg-inkscape/jc-02-float-struct32_svg-tex.pdf index 78488cf..57138f2 100644 Binary files a/svg-inkscape/jc-02-float-struct32_svg-tex.pdf and b/svg-inkscape/jc-02-float-struct32_svg-tex.pdf differ diff --git a/svg-inkscape/jc-02-float-struct32_svg-tex.pdf_tex b/svg-inkscape/jc-02-float-struct32_svg-tex.pdf_tex index 47c74d7..25c4b62 100644 --- a/svg-inkscape/jc-02-float-struct32_svg-tex.pdf_tex +++ b/svg-inkscape/jc-02-float-struct32_svg-tex.pdf_tex @@ -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) %% diff --git a/svg-inkscape/jc-02-float-struct_svg-tex.pdf b/svg-inkscape/jc-02-float-struct_svg-tex.pdf index 5295481..39abbce 100644 Binary files a/svg-inkscape/jc-02-float-struct_svg-tex.pdf and b/svg-inkscape/jc-02-float-struct_svg-tex.pdf differ diff --git a/svg-inkscape/jc-02-float-struct_svg-tex.pdf_tex b/svg-inkscape/jc-02-float-struct_svg-tex.pdf_tex index 2e4181f..447b98b 100644 --- a/svg-inkscape/jc-02-float-struct_svg-tex.pdf_tex +++ b/svg-inkscape/jc-02-float-struct_svg-tex.pdf_tex @@ -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) %% diff --git a/svg-inkscape/jc-03-class-obj-fields_svg-tex.pdf b/svg-inkscape/jc-03-class-obj-fields_svg-tex.pdf index d7ae25c..1ba2d30 100644 Binary files a/svg-inkscape/jc-03-class-obj-fields_svg-tex.pdf and b/svg-inkscape/jc-03-class-obj-fields_svg-tex.pdf differ diff --git a/svg-inkscape/jc-03-class-obj-fields_svg-tex.pdf_tex b/svg-inkscape/jc-03-class-obj-fields_svg-tex.pdf_tex index 1b45307..91c963d 100644 --- a/svg-inkscape/jc-03-class-obj-fields_svg-tex.pdf_tex +++ b/svg-inkscape/jc-03-class-obj-fields_svg-tex.pdf_tex @@ -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) %% diff --git a/svg-inkscape/jc-03-class-obj-full_svg-tex.pdf b/svg-inkscape/jc-03-class-obj-full_svg-tex.pdf index f3c8344..e87b7a1 100644 Binary files a/svg-inkscape/jc-03-class-obj-full_svg-tex.pdf and b/svg-inkscape/jc-03-class-obj-full_svg-tex.pdf differ diff --git a/svg-inkscape/jc-03-class-obj-full_svg-tex.pdf_tex b/svg-inkscape/jc-03-class-obj-full_svg-tex.pdf_tex index c06a208..02686aa 100644 --- a/svg-inkscape/jc-03-class-obj-full_svg-tex.pdf_tex +++ b/svg-inkscape/jc-03-class-obj-full_svg-tex.pdf_tex @@ -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) %% diff --git a/svg-inkscape/jc-03-class-obj-nostatic_svg-tex.pdf b/svg-inkscape/jc-03-class-obj-nostatic_svg-tex.pdf index 45d884b..e87b7a1 100644 Binary files a/svg-inkscape/jc-03-class-obj-nostatic_svg-tex.pdf and b/svg-inkscape/jc-03-class-obj-nostatic_svg-tex.pdf differ diff --git a/svg-inkscape/jc-03-class-obj-nostatic_svg-tex.pdf_tex b/svg-inkscape/jc-03-class-obj-nostatic_svg-tex.pdf_tex index 800eb95..940d66d 100644 --- a/svg-inkscape/jc-03-class-obj-nostatic_svg-tex.pdf_tex +++ b/svg-inkscape/jc-03-class-obj-nostatic_svg-tex.pdf_tex @@ -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) %%