\documentclass[j-spec.tex]{subfiles} \usepackage{spreadtab} \begin{document} \section{Семинар: Обобщения} \subsection{Инструментарий} \begin{itemize} \item \href{https://docs.google.com/presentation/d/1rWHGQBITRElvyKFEjwe8dOinDbAV2ZW18tAK1FXU48U/edit?usp=share_link}{Презентация} для преподавателя, ведущего семинар; \item \href{https://drive.google.com/file/d/1LWyE8aEy4-1gsognqhXIXwDcoLviVge4/view}{Фон} GeekBrains для проведения семинара в Zoom; \item JDK любая 11 версии и выше; \item \href{https://www.jetbrains.com/idea/download}{IntelliJ IDEA Community Edition} для практики и примеров используется IDEA. \end{itemize} \subsection{Цели семинара} \begin{itemize} \item Практика создания простых обобщений; \item Создание собственного обобщённого контейнера с описанием базовых алгоритмов (введение в коллекции); \item Изучение поведения объекта итератора; \item Закрепление понимания механизмов работы коллекций. \end{itemize} \subsection{План-содержание} \noindent \begin{spreadtab}{{longtable}{|p{37mm}|l|l|p{90mm}|}} \hline @ Что происходит & @ Время & @ Слайды & @ Описание \\ \hline \endhead @ Организационный момент & 5 tag(beg) & @ 1-5 & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучивает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\ \hline @ Quiz & 5 & @ 6-18 & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (по минуте на ответ) \\ \hline @ Рассмотрение ДЗ лекции & 10 & @ 19-23 & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\ \hline @ Вопросы и ответы & 10 & @ 24 & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\ \hline @ Задание 1 & 10 & @ 25-27 & @ Формирование навыков базовой работы с обобщениями \\ \hline @ Задание 2 & 20 & @ 28-30 & @ Практика написания обобщённого кода с дополнительным описанием алгоритмов манипулирования данными \\ \hline @ Перерыв (если нужен) & 5 & @ 31 & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\ \hline @ Задание 3 & 20 & @ 32-34 & @ Изучение поведения итератора для понимания механизмов его действия и необходимости его использования в работе \\ \hline @ Задание 4 & 20 & @ 35-38 & @ Закрепление понимания механизмов работы коллекций (в том числе с применением итераторов) \\ \hline @ Домашнее задание & 5 & @ 39-40 & @ Объясните домашнее задание, подведите итоги урока \\ \hline @ Рефлексия & 10 tag(end) & @ 41-42 & @ Преподаватель запрашивает обратную связь \\ \hline @ Длительность & sum(cell(beg):cell(end)) & & \\ \hline \end{spreadtab} \subsection{Подробности} \subsubsection*{Организационный момент} \begin{itemize} \item \textbf{Цель этапа:} Позитивно начать урок, создать комфортную среду для обучения. \item \textbf{Тайминг:} 3-5 минут. \item \textbf{Действия преподавателя:} \begin{itemize} \item Запрашивает активность от аудитории в чате; \item Презентует цели курса и семинара; \item Презентует краткий план семинара и что студент научится делать. \end{itemize} \end{itemize} \subsubsection*{Quiz} \begin{itemize} \item \textbf{Цель этапа:} Вовлечение аудитории в обратную связь. \item \textbf{Тайминг:} 5--7 минут (4 вопроса, по минуте на ответ). \item \textbf{Действия преподавателя:} \begin{itemize} \item Преподаватель задаёт вопросы викторины, представленные на слайдах презентации; \item через 30 секунд демонстрирует слайд-подсказку и ожидает ответов. \end{itemize} \item \textbf{Вопросы и ответы:} \begin{enumerate} \item Какая основная цель использования Java generics? (1) \begin{enumerate} \item Упрощение программирования и повышение безопасности типов \item Ускорение работы программы и сокращение объема кода \item Позволяют работать с различными базами данных одновременно \end{enumerate} % Неверные ответы: b) и c) - generics не связаны с ускорением работы программы или работой с базами данных, их основная цель - добавить типовую безопасность и упростить программирование. \item Что такое параметризованный класс в Java generics? (1) \begin{enumerate} \item Класс, который принимает параметр типа \item Класс, который имеет только один параметр типа \item Класс, который можно использовать только с определенным типом данных \end{enumerate} % Неверные ответы: b) и c) - параметризованный класс может иметь любое количество параметров типа и может быть использован с различными типами данных. \item Какие ограничения можно использовать с wildcard в Java generics? (1) \begin{enumerate} \item extends и super \item only \item extends \end{enumerate} % Неверные ответы: b) и c) - в generics для ограничения типа используются ключевые слова extends и super, а не only или extends. \item Можно ли создать экземпляр обобщенного типа в Java, внутри класса, описывающего этот тип? (2) \begin{enumerate} \item Да, это возможно \item Нет, такое создание экземпляров обобщенных типов запрещено \item Это зависит от контекста использования обобщенного типа \end{enumerate} % Неверные ответы: a) и c) - экземпляры обобщенных типов не могут быть созданы в Java из-за стирания типов, однако можно создать экземпляр обобщенного класса, указав конкретный тип данных. \end{enumerate} \end{itemize} \subsubsection*{Рассмотрение ДЗ} \begin{itemize} \item \textbf{Цель этапа:} Пояснить не очевидные моменты в формулировке ДЗ с лекции, синхронизировать прочитанный на лекции материал к началу семинара. \item \textbf{Тайминг:} 15-20 минут. \item \textbf{Действия преподавателя:} \begin{itemize} \item Преподаватель демонстрирует свой вариант решения домашнего задания из лекции; \item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов. \end{itemize} \item \textbf{Домашнее задание из лекции:} \begin{itemize} \item Написать метод, который меняет два элемента массива местами (массив может быть любого ссылочного типа); \textbf{Вариант решения} Задание с подвохом, при решении необязательно было использовать дженерики, формулировка задания не ограничивает используемые в массиве типы, наоборот, явно проговаривается, что массив может быть любого типа. \begin{lstlisting}[language=Java,style=JCodeStyle] private static void swap(Object[] arr, int from, int to) { Object temp = arr[from]; arr[from] = arr[to]; arr[to] = temp; } public static void main(String[] args) { Object[] arr = {1, 2.0f, "hello"}; System.out.println(Arrays.toString(arr)); swap(arr, 0, 2); System.out.println(Arrays.toString(arr)); } \end{lstlisting} \item Большая задача: \begin{itemize} \item Есть классы \code{Fruit} -> \code{Apple}, \code{Orange}; (больше не надо); \item Класс \code{Box} в который можно складывать фрукты, коробки условно сортируются по типу фрукта, поэтому в одну коробку нельзя сложить и яблоки, и апельсины; Для хранения фруктов внутри коробки можете использовать \code{ArrayList}; \item Сделать метод \code{getWeight()} который высчитывает вес коробки, зная количество фруктов и вес одного фрукта(вес яблока -- \code{1.0f}, апельсина -- \code{1.5f}, не важно в каких единицах); \item Внутри класса коробки сделать метод \code{compare()}, который позволяет сравнить текущую коробку с той, которую подадут в \code{compare()} в качестве параметра, \code{true} -- если их веса равны, \code{false} в противном случае (коробки с яблоками возможно сравнивать с коробками с апельсинами); \item Написать метод, который позволяет пересыпать фрукты из текущей коробки в другую коробку (при этом, нельзя яблоки высыпать в коробку с апельсинами), соответственно, в текущей коробке фруктов не остается, а в другую перекидываются объекты, которые были в этой коробке. \end{itemize} \textbf{Вариант решения} Создали фрукты с каким то разным весом, создали коробку, которая может вместить только фрукты. Надо фрукты там как то хранить, поэтому -- список. Соответственно при создании можем в нашу коробку какие то фрукты накидать. Соответственно метод, который будет уметь добавлять фрукты в коробку \begin{lstlisting}[language=Java,style=JCodeStyle,caption={ }] private interface Fruit { float getWeight(); } private static class Apple implements Fruit { static final float weight = 1.0f; @Override public float getWeight() { return weight; } } private static class Orange implements Fruit { static final float weight = 1.5f; @Override public float getWeight() { return weight; } } public static class Box { private final List container; Box(T[] init) { container = new ArrayList<>(); for (T f : init) { add(f); } } void add(T fruit) { container.add(fruit); } void print() { System.out.println(getWeight()); } } \end{lstlisting} Поскольку в коробке у нас могут быть только одно типа фрукты -- мы можем не перебирать каждый из них, а умножить вес одного на количество. \begin{lstlisting}[language=Java,style=JCodeStyle,caption={ }] float getWeight() { return (container.isEmpty()) ? 0 : container.get(0).getWeight() * container.size(); } \end{lstlisting} Можно было, по большому счёту, переопределить метод equals() или написать свой метод compare() который принимает вторую коробку и сравнивает вес. Сравнивать можно любые фрукты, значит в методе не подходит параметр типа \code{} \begin{lstlisting}[language=Java,style=JCodeStyle,caption={ }] boolean compare(Box with) { return this.getWeight() - with.getWeight() < 0.0001; } \end{lstlisting} Осталось только уметь пересыпать из одной коробки в другую не смешивая. На входе должна быть коробка того же типа, что и у объекта, и тут два пути, либо пересыпать всё из текущей коробки в другую, либо из другой в текущую, метод назван \code{transferTo()}, поэтому пересыпаться фрукты будут из текущей коробки. Возникает вопрос: если создаётся коробка с яблоками \code{Box} и коробка с фруктами \code{Box}, должна ли быть возможность перекинуть из яблочной во фруктовую? Однозначно, нет. Поэтому, в аргументе метода используется \code{Box}, таким образом яблоки возможно кидать в яблоки или в яблочных родителей, но не в апельсины. \begin{lstlisting}[language=Java,style=JCodeStyle,caption={ }] void transferTo(Box dest) { dest.container.addAll(container); container.clear(); } \end{lstlisting} \end{itemize} \end{itemize} \subsubsection*{Вопросы и ответы} \begin{itemize} \item \textbf{Ценность этапа} Вовлечение аудитории в обратную связь, пояснение неочевидных моментов в материале лекции и другой проделанной работе. \item \textbf{Тайминг} 5-15 минут \item \textbf{Действия преподавателя} \begin{itemize} \item Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы; \item Если преподаватель затрудняется с ответом, необходимо мягко предложить студенту ответить на его вопрос на следующем семинаре (и не забыть найти ответ на вопрос студента!); \item Предложить и показать пути самостоятельного поиска студентом ответа на заданный вопрос; \item Посоветовать литературу на тему заданного вопроса; \item Дополнительно указать на то, что все сведения для выполнения домашнего задания, прохождения викторины и работы на семинаре были рассмотрены в методическом материале к этому или предыдущим урокам. \end{itemize} \end{itemize} \subsubsection*{Задание 1} \begin{itemize} \item \textbf{Ценность этапа} Формирование навыков базовой работы с обобщениями. \item \textbf{Тайминг} 10-15 мин \item \textbf{Действия преподавателя} \begin{itemize} \item Выдать задание студентам; \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций; \item Пояснить студентам пользу и необходимость следования паттерну MVC, проговорить важность разделения логики и открывающиеся возможности при правильном проектировании. \end{itemize} \item \textbf{Задание}: \begin{itemize} \item Создать обобщенный класс с тремя параметрами (\code{T}, \code{V}, \code{K}). Класс содержит три переменные типа (\code{T}, \code{V}, \code{K}), конструктор, принимающий на вход параметры типа (\code{T}, \code{V}, \code{K}), методы возвращающие значения трех переменных. Создать метод, выводящий на консоль имена классов для трех переменных класса. Наложить ограничения на параметры типа: \code{T} должен реализовать интерфейс \code{Comparable} (классы оболочки, \code{String}), \code{V} должен реализовать интерфейс \code{DataInput} и расширять класс \code{InputStream}, \code{K} должен расширять класс \code{Number}. \textbf{Вариант решения} \begin{lstlisting}[language=Java,style=JCodeStyle] private static class MyClass { T t; V v; K k; MyClass(T t, V v, K k) { this.t = t; this.v = v; this.k = k; } public T getT() { return t; } public V getV() { return v; } public K getK() { return k; } void print() { System.out.printf("t = %s, v = %s, k = %s", t.getClass().getName(), v.getClass().getName(), k.getClass().getName()); } } \end{lstlisting} \end{itemize} \end{itemize} \subsubsection*{Задание 2} \begin{itemize} \item \textbf{Ценность этапа} Практика написания обобщённого кода с дополнительным описанием алгоритмов манипулирования данными. \item \textbf{Тайминг} 15-20 мин \item \textbf{Действия преподавателя} \begin{itemize} \item Выдать задание студентам; \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций; \item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой». \end{itemize} \item \textbf{Задание}: \begin{itemize} \item Описать собственную коллекцию -- список на основе массива. Коллекция должна иметь возможность хранить любые типы данных, иметь методы добавления и удаления элементов. \textbf{Вариант решения} \begin{lstlisting}[language=Java,style=JCodeStyle] private static class OwnList { Object[] arr; int count; OwnList() { arr = new Object[1]; count = 0; } void add(T item) { if (count == arr.length) { Object[] newArr = new Object[arr.length * 2]; System.arraycopy(arr, 0, newArr, 0, arr.length); arr = newArr; } arr[count++] = item; } T remove() { if (count == 0) throw new NoSuchElementException(); T temp = (T) arr[--count]; arr[count] = null; return temp; } @Override public String toString() { return Arrays.toString(arr); } } \end{lstlisting} \end{itemize} \end{itemize} \subsubsection*{Задание 3} \begin{itemize} \item \textbf{Ценность этапа} Изучение поведения итератора для понимания механизмов его действия и необходимости его использования в работе. \item \textbf{Тайминг} 20-25 мин \item \textbf{Действия преподавателя} \begin{itemize} \item Выдать задание студентам; \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций; \end{itemize} \item \textbf{Задание}: \begin{itemize} \item Написать итератор по массиву. Итератор -- это объект, осуществляющий движение по коллекциям любого типа, содержащим любые типы данных. Итераторы обычно имеют только два метода -- проверка на наличие следующего элемента и переход к следующему элементу. Но также, особенно в других языках программирования, возможно встретить итераторы, реализующие дополнительную логику. \textbf{Вариант решения} \begin{lstlisting}[language=Java,style=JCodeStyle] private static class ArrayIterator { private final T[] array; private int index = 0; public ArrayIterator(T[] array) { this.array = array; } public boolean hasNext() { return index < array.length; } public T next() { if(!hasNext()) throw new NoSuchElementException(); return array[index++]; } } public static void main(String[] args) { Integer[] arr = {1,2,3,4}; ArrayIterator it = new ArrayIterator<>(arr); while (it.hasNext()) { System.out.print(it.next() + " "); } } \end{lstlisting} \item [$*_1$] Написать итератор таким образом, чтобы его возможно было использовать для цикла \code{foreach}. \textbf{Вариант решения} Указать, что для этого достаточно реализовать интерфейс \code{Iterator}. \begin{lstlisting}[language=Java,style=JCodeStyle] class ArrayIterator implements Iterator{ private T[] array; private int index = 0; public ArrayIterator(T[] array) { this.array = array; } @Override public boolean hasNext() { return index < array.length; } @Override public T next() { if(!hasNext()) throw new NoSuchElementException(); return array[index++]; } } \end{lstlisting} \end{itemize} \end{itemize} \subsubsection*{Задание 4} \begin{itemize} \item \textbf{Ценность этапа} Закрепление понимания механизмов работы коллекций (в том числе с применением итераторов). \item \textbf{Тайминг} 20-25 мин \item \textbf{Действия преподавателя} \begin{itemize} \item Выдать задание студентам; \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций; \end{itemize} \item \textbf{Задание}: \begin{itemize} \item Описать интерфейс \code{Person} с методами \code{doWork()} и \code{haveRest()}. Написать два класса работник и бездельник, реализующих интерфейс. Работник работает, и не умеет бездельничать, в то время как бездельник не умеет работать, но умеет отдыхать. Написать обобщённые классы \code{Workplace} и \code{Club}, содержащие массив из \code{Person}. В классах необходимо вызывать у всего массива людей вызывать соответствующие методы. \textbf{Вариант решения} \begin{lstlisting}[language=Java,style=JCodeStyle] interface Person { void doWork(); void haveRest(); } private static class Worker implements Person { @Override public void doWork() { System.out.println("Work!"); } @Override public void haveRest() { System.out.println("What?"); } } private static class Idler implements Person { @Override public void doWork() { System.out.println("No!"); } @Override public void haveRest() { System.out.println("Chill!"); } } private static class Workplace { Person[] arr; public Workplace(T... people) { arr = people; } void work() { for (Person person : arr) { person.doWork(); } } } private static class Club { Person[] arr; public Club(T... people) { arr = people; } void chill() { for (Person person : arr) { person.haveRest(); } } } public static void main(String[] args) { Workplace w = new Workplace<>(new Worker(), new Worker(), new Idler()); Club c = new Club<>(new Worker(), new Worker(), new Idler()); w.work(); c.chill(); } \end{lstlisting} \end{itemize} \end{itemize} \subsubsection*{Домашнее задание} \begin{itemize} \item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями. \item \textbf{Тайминг} 5-10 минут. \item \textbf{Действия преподавателя} \begin{itemize} \item Пояснить студентам в каком виде выполнять и сдавать задания \item Уточнить кто будет проверять работы (преподаватель или ревьювер) \item Объяснить к кому обращаться за помощью и где искать подсказки \item Объяснить где взять проект заготовки для дз \end{itemize} \item \textbf{Задания} \begin{enumerate} \item [5-25 мин] Выполнить все задания семинара, если они не были решены, без ограничений по времени; \textbf{Все варианты решения приведены в тексте семинара выше} \item [25 мин] 1. Внедрить итератор из задания 2 в коллекцию, написанную в задании 3 таким образом, чтобы итератор был внутренним классом и, соответственно, объектом в коллекции. \begin{lstlisting}[language=Java,style=JCodeStyle] private static class OList implements Iterable { class ArrayIterator implements Iterator { private int index = 0; @Override public boolean hasNext() { return index < count; } @Override public T next() { if(!hasNext()) throw new NoSuchElementException(); return (T) arr[index++]; } } Object[] arr; int count; Main.OList.ArrayIterator iter; OList() { arr = new Object[1]; count = 0; this.iter = new ArrayIterator(); } void add(T item) { if (count == arr.length) { Object[] newArr = new Object[arr.length * 2]; System.arraycopy(arr, 0, newArr, 0, arr.length); arr = newArr; } arr[count++] = item; } T remove() { if (count == 0) throw new NoSuchElementException(); --count; T temp = (T) arr[count]; arr[count] = null; return temp; } @Override public Iterator iterator() { return iter; } @Override public Spliterator spliterator() { return Iterable.super.spliterator(); } @Override public String toString() { return Arrays.toString(arr); } } \end{lstlisting} \item [15 мин] 2. Написать класс Калькулятор (необобщенный), который содержит обобщенные статические методы: \code{sum()}, \code{multiply()}, \code{divide()}, \code{subtract()}. Параметры этих методов -- два \textbf{числа} разного типа, над которыми должна быть произведена операция. \begin{lstlisting}[language=Java,style=JCodeStyle] private static class Calculator { public static double sum(T num1, U num2) { return num1.doubleValue() + num2.doubleValue(); } public static double multiply(T num1, U num2) { return num1.doubleValue() * num2.doubleValue(); } public static double divide(T num1, U num2) { return num1.doubleValue() / num2.doubleValue(); } public static double subtract(T num1, U num2) { return num1.doubleValue() - num2.doubleValue(); } } public static void main(String[] args) { System.out.println(Calculator.sum(2, 2.0)); System.out.println(Calculator.multiply(2.0f, 2.0)); System.out.println(Calculator.divide(2L, 2.0)); System.out.println(Calculator.subtract(2, 2)); } \end{lstlisting} \item [10 мин] 3. Напишите обобщенный метод \code{compareArrays()}, который принимает два массива и возвращает \code{true}, если они одинаковые, и \code{false} в противном случае. Массивы могут быть любого типа данных, но должны иметь одинаковую длину и содержать элементы одного типа. \begin{lstlisting}[language=Java,style=JCodeStyle] private static boolean compareArrays(T[] array1, T[] array2) { if (array1.length != array2.length) { return false; } for (int i = 0; i < array1.length; i++) { if (!array1[i].equals(array2[i])) { return false; } } return true; } \end{lstlisting} \item [10 мин] 4. Напишите обобщенный класс \code{Pair}, который представляет собой пару значений разного типа. Класс должен иметь методы \code{getFirst()}, \code{getSecond()} для получения значений пары, а также переопределение метода \code{toString()}, возвращающее строковое представление пары. \begin{lstlisting}[language=Java,style=JCodeStyle] private static class Pair { private T1 first; private T2 second; public Pair(T1 first, T2 second) { this.first = first; this.second = second; } public T1 getFirst() { return first; } public T2 getSecond() { return second; } @Override public String toString() { return "(" + first + ", " + second + ")"; } } public static void main(String[] args) { Pair pair1 = new Pair<>(1, "one"); System.out.println(pair1.getFirst()); // 1 System.out.println(pair1.getSecond()); // "one" System.out.println(pair1); // "(1, one)" Pair pair2 = new Pair<>("pi", 3.14); System.out.println(pair2.getFirst()); // "pi" System.out.println(pair2.getSecond()); // 3.14 System.out.println(pair2); // "(pi, 3.14)" } \end{lstlisting} \end{enumerate} \end{itemize} \subsubsection*{Рефлексия и завершение семинара} \begin{itemize} \item \textbf{Цель этапа:} Привести урок к логическому завершению, посмотреть что студентам удалось, что было сложно и над чем нужно еще поработать \item \textbf{Тайминг:} 5-10 минут \item \textbf{Действия преподавателя:} \begin{itemize} \item Запросить обратную связь от студентов. \item Подчеркните то, чему студенты научились на занятии. \item Дайте рекомендации по решению заданий, если в этом есть необходимость \item Дайте краткую обратную связь студентам. \item Поделитесь ощущением от семинара. \item Поблагодарите за проделанную работу. \end{itemize} \end{itemize} \newpage \end{document}