diff --git a/pics/jd-02-action-listener.svg b/pics/jd-02-action-listener.svg new file mode 100644 index 0000000..0bf62bb --- /dev/null +++ b/pics/jd-02-action-listener.svg @@ -0,0 +1,832 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Внешний мир + + Логика приложения + Операционная система и SDK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OK + + + + + + + public interface + class implements interface + + действие + действие + действие + драйвер + драйвер + фреймворк + void pressButton(); + void pressKey(); + void clickAction(); + addActionListener(); + @Overridevoid pressButton() \{...\} + @Overridevoid pressKey() \{...\} + @Overridevoid clickAction() \{...\} + + + + + + + + + + + + + + + diff --git a/scenarios/jtd2-07b.tex b/scenarios/jtd2-07b.tex index b07c4cc..898ed60 100644 --- a/scenarios/jtd2-07b.tex +++ b/scenarios/jtd2-07b.tex @@ -13,7 +13,7 @@ На прошлом уроке & На прошлом уроке мы поговорили как раз о графических интерфейсах пользователя. создали немного окон, разместили немного компонентов, порисовали. Поговорили о графических интерфейсах через призму создания и взаимодействия объектов, нарисовали пару-тройку диаграмм, чтобы лучше запомнить, что как и с чем связывается, кто кого вызывает и зачем. \\ \hline -На этом уроке & Поговорим об интерфейсах, рассмотрим понятие и принцип работы, поговорим о ключевом слове implements; Наследование и множественное наследование интерфейсов, реализация, значения по умолчанию и частичная реализация интерфейсов. Естественно, что говоря об интерфейсах нельзя не сказать о функциональных интерфейсах и анонимных классах. Коротко рассмотрим модификаторы доступа при использовании интерфейсов и немного подробнее поговорим о глубинных процессах, таких как раннее и позднее связывание в объектно-ориентированном программировании. \\ \hline +На этом уроке & Поговорим об интерфейсах, рассмотрим понятие и принцип работы, поговорим о ключевом слове implements; Наследование и множественное наследование интерфейсов, реализация, значения по умолчанию и частичная реализация интерфейсов. Естественно, что говоря об интерфейсах нельзя не сказать о функциональных интерфейсах и анонимных классах. Коротко рассмотрим модификаторы доступа при использовании интерфейсов. \\ \hline 06-01 & Разговор об интерфейсах хотелось бы построить не так, как мы это делали на лекциях обычно, а от некоторой практической составляющей, чтобы где-то в середине лекции у вас сложилось явное впечатление, что что-то тут явно можно улучшить, а когда мы применим интерфейсы, вы подумали «ааааа так вот зачем оно нужно и как применяется», а потом уже поговорим о теоретической составляющей и особенностях. \\ \hline @@ -111,86 +111,78 @@ 06-27 & Насладимся летающими шариками в одном приложении, и летающими квадратиками в другом. Теперь на основе нашего очень хорошо отделённого интерфейсами общего пакета можно штамповать такие приложения практически без усилий. Понимаете, как разработчики в игровых студиях делают по сотне очень похожих игр в год? \\ \hline -06-28 & Дефолтная реализация интерфейса \\ \hline - & \\ \hline - & \\ \hline +06-28 & Непосредственно об интерфейсах осталось сказать, что интерфейсы были значительно переработаны в джаве 1.8, туда добавили довольно много интересных механизмов, и об одном из них нельзя не сказать. Дефолтная реализация интерфейса. Как и всю остальную сегодняшнюю лекцию, хочу начать с примера применения. И пример я хочу построить на основе тех интерфейсов, которые у нас уже написаны - человек и бык. Понятно же, что именно у этих интерфейсов явно есть реализации по-умолчанию, например, для действия ходить, человек ходит на двух ногах, а бык на четырёх копытах. Есть и исключительные случаи, но они чаще всего связаны с чем-нибудь грустным, поэтому поступим логично и скажем, что у обоих интерфейсов будет реализация метода перемещения по-умолчанию. для этого понадобится ключевое слово дефолт. Обратите внимание, что в интерфейсе быка я не использовал это ключевое слово, и среда разработки мне подсказала, что так писать нельзя. \\ \hline -отбивка Анонимные классы & Программные интерфейсы открывают перед разработчиком широчайшие возможности по написанию более выразительного кода. Одна из наиболее часто используемых возможностей - анонимные классы. \\ \hline +06-29 & Какие особенности есть у реализующих методы по-умолчанию интерфейсов? Первое, и самое очевидное - отсутствие необходимости переопределять вообще все методы в классах, реализующих эти интерфейсы, что делает интерфейс чуть более похожим на класс. Реализованные по-умолчанию интерфейсы могут задействовать созданные в этом интерфейсе поля, а наличие в интерфейсе полей делает его ещё более похожим на класс. На слайде можно видеть, что написанные перед полями модификаторы были отмечены средой разработки как избыточные и необязательные к написанию. Если убрать ключевые слова стэтик или файнал - ничего не изменится, а вот если заменить паблик на, скажем, прайвэт - будет ошибка компиляции, поля интерфейса всегда публичные и явно их приватить - нельзя. \\ \hline -06-25 & Итак, мы уже неплохо знаем, что классы -- это такой новый для нашей программы тип данных. Мы уже привычными движениями создаём публичные классы в отдельный файлах и пишем в них логику, но это не всё, что позволяет нам джава. Классы также бывают вложенными и внутренними. Внутренние классы - это классы, которые пишутся внутри класса, который описан в файле, мы его даже можем использовать и вызывать его методы. А также вложенные или локальные классы, которые мы можем объявлять прямо в методах, и работать с ними, как с обычными классами, но область видимости у них будет только внутри метода. Это мы уже тоже прошли. К чему я это веду? к анонимным классам. Создадим интерфейс, назовём его как-нибудь хорошо, например, MouseListener и опишем в нём пару методов, например mouseUp(), mouseDown(). Перейдя в основной класс можем написать, что некоторый локальный класс будет реализовывать интерфейс и значит должен переопределять все его методы. После чего мы привычно можем экземпляр этого класса создать и даже попользоваться его методами. Удобно, привычно, хорошо. \\ \hline +06-30 & Программные интерфейсы открывают перед разработчиком широчайшие возможности по написанию более выразительного кода. Одна из наиболее часто используемых возможностей - анонимные классы.\\ \hline -06-26 & Очень часто, какие-то элементы управления (кнопчки, события входящих датчиков (клавиатура, мышка), сеть требуют на вход каких-нибудь обработчиков своих данных, которые будут внимательно слушать конкретный источник данных, отлавливать события и вообще знать что делать. Это всё делается через интерфейсы. Значит если мы в такой элемент управления в качестве слушателя передадим что-то, что реализует нужный интерфейс, то это нечто, очевидно, объект, уже начнёт ловить события и как-то их обрабатывать. Соответственно, весьма часто такие классы создаются не просто без названия экземпляра, но и вовсе без имени, прямо в аргументе методов. \\ \hline +06-31 & Итак, мы уже неплохо знаем, что классы -- это такой новый для нашей программы тип данных. Мы уже привычными движениями создаём публичные классы в отдельных файлах и пишем в них логику, но это не всё, что позволяет нам джава. Классы также бывают вложенными и внутренними. Внутренние классы - это классы, которые пишутся внутри класса, который описан в файле, мы его даже можем использовать и вызывать его методы. А также вложенные или локальные классы, которые мы можем объявлять прямо в методах, и работать с ними, как с обычными классами, но область видимости у них будет только внутри метода. Это мы уже тоже прошли. К чему я это веду? к анонимным классам. Анонимный класс, что довольно очевидно - это класс без названия. Создадим интерфейс, назовём его как-нибудь хорошо, например, MouseListener и опишем в нём пару методов, например mouseUp(), mouseDown(). Перейдя в основную часть программы можем написать, что некоторый локальный класс будет реализовывать интерфейс и значит должен переопределять все его методы. После чего мы привычно можем экземпляр этого класса создать и даже попользоваться его методами. Удобно, привычно, хорошо. \\ \hline -06-27 & Придумаем какой-нибудь метод, принимающий на вход наш только что созданный МаусЛистенер. Ну и действительно, зачем ему имя, если он будет использован только один раз и только в этом методе? То есть передать туда экземпляр нашего маусЛистнера - несложно и привычно, мы уже создали класс, реализующий интерфейс маусЛистенер, создадим объект и передадим в метод. +06-32 & Очень часто, какие-то элементы управления (кнопчки, события входящих датчиков (клавиатура, мышка), сеть требуют на вход каких-нибудь обработчиков своих данных, которые будут внимательно слушать конкретный источник данных, отлавливать события и вообще знать что делать. Это всё делается через интерфейсы. С точки зрения программы, создаётся какой-то метод, например, добавления к кнопке слушателя, вы должны помнить, мы такие делали для кнопок в приложении, которое играет с пользователем в крестики-нолики, там как раз интерфейс назывался экшн листенер. Значит если мы в элемент управления в качестве слушателя передадим что-то, что реализует нужный интерфейс, то это нечто, очевидно, объект, начнёт ловить события и как-то их обрабатывать. Мы это делали и в летающих шариках, чтобы отвязать вызов метода объектом от знания о классе реализующем этот метод.\\ \hline -Вот допустим у нас есть переменная MouseListener listener и нам нужно создать туда какой-то экземпляр, который реализует этот интерфейс. для этого есть такой синтаксис: - new MouseListener дальше пишем интерфейс, который реализуем - {} и у нас по сути открывается объявление класса, где мы пишем реализацию. И получается что мы создаём один экземпляр анонимного класса, который реализует интерфейс MouseListener. И конечно потом мы этот анонимный класс уже кладём в идентификатор (или можем прям вот так передать в метод). Конечно мы можем избежать этого, сейчас поговорим как, но в чужом коде это сплошь и рядом, вот такой замороченный синтаксис, спасибо разработчикам джава. - Понятен-ли этот синтаксис? Это создание объекта анонимного класса, никак не называющегося, реализующего интерфейс. - Тут можно поговорить о лямбдах, для того чтобы сократить синтаксис мы можем просто убрать то что неизменно для этого анонимного класса - название интерфейса, название метода и класс аргумента. \\ \hline +06-33 & Придумаем для текущего примера какой-нибудь метод, принимающий на вход только что созданный МаусЛистенер. И в метод передаём объект, а внутри объекта для данного конкретного случая написали, как именно должна вести себя программа, когда кто-то нажал или отпустил кнопку мышки. Соответственно, весьма часто такие классы создаются не просто без названия экземпляра, но и вовсе без имени, прямо в аргументе методов. Ну и действительно, зачем ему имя, если он будет использован только один раз и только в этом методе? То есть, передать в метод экземпляр адаптера, реализующего маусЛистнер - несложно и привычно, мы это можем и понимаем. +%% 2 +Вот допустим у нас есть параметр метода MouseListener m и нужно создать туда какой-то экземпляр, который реализует этот интерфейс. Но у нас уже есть класс, который это делает: маусАдаптер. Можем создать новый экземпляр адаптера, но без идентификатора, зачем он нужен, если адаптер сразу передаётся в метод и больше никак не используется? +%% 3 - & \\ \hline - & \\ \hline - & \\ \hline +Вроде классно, избавились от одной лишней переменной, но можно и ещё лучше. Класс маусАдаптера идеально выполняет критерий С из принципов СОЛИД - сингл респонсибилити - делает только одно полезное дело - реализует интерфейс маус листнера. Но раз дело только одно - можно его выполнять и без размышлений о названии класса. Создадим сразу интерфейсную переменную и сохраним реализацию в неё. Для этого есть такой немного необычный синтаксис, который мы видим на 36й строке - new MouseListener, круглые скобки и дальше пишем интерфейс, который реализуем в фигурных скобках. Пустые круглые скобки намекают нам на то, что это вызов конструктора, а фигурные намекают на тело класса, то есть по сути мы пишем класс, где мы пишем реализацию и который тут же инстанциируем. Более формально, получается что мы создаём один экземпляр анонимного класса, который реализует интерфейс MouseListener. И конечно потом мы этот анонимный класс уже кладём в идентификатор. +%% 4 + +А можем даже не создавать интерфейсный идентификатор, а сразу передать реализующий экземпляр в аргумент метода. Получается, что мы в метод передаём новый экземпляр анонимного класса который РЕАЛИЗУЕТ ИНТЕРФЕЙС слушателя, и вот здесь же, как раз описание этого класса, мы в нём переопределяем соответствующие методы. Вот так это читается. Получается, что сейчас на слайде представлены все способы реализации интерфейса и передачи его в функцию при помощи анонимных классов. Ещё раз, анонимные классы это классы, не имеющие названия и реализующие какой-то интерфейс. Тут можно поговорить о лямбдах, в так называемых функциональных интерфейсах, то есть в интерфейсах, содержащих только один методд, для того чтобы сократить синтаксис, можно просто убрать то, что неизменно для этого анонимного класса - название интерфейса, название метода и класс аргумента, получив довольно лаконичную запись, но это гораздо более широкая тема, о ней мы ещё обязательно поговорим. \\ \hline + +06-34 & Конечно, мы можем избежать использования анонимных классов, тем более, что часто они могут занимать довольно много места, сейчас поговорим как, но в чужом коде их использвоание можно встретить сплошь и рядом. Первое, что придумали делать - это адаптеры. Например, для панели на которой мы только что рисовали летающие шарики есть слушатель и метод добавления слушателя мышки, очень похожий на тот, который был только что создан в учебных целях, только не игрушечный. Если начать в аргументах этого метода писать «нью что-нибудь», идея предложит реализовать интерфейс маус листнера, но также предложит ещё один вариант - какой-то маус адаптер. Я напоминаю, что все исходные коды всего языка джава открыты, их можно и даже нужно читать время от времени. Так вот, если открыть исходники маус адаптера, можно увидеть, что это класс, реализующий несколько интерфейсов, но только формально, то есть все реализации пустые. Это позволяет нам вполне легально переопределять не все, а только некоторые методы интерфейса, значительно экономя место в коде приложения, если нам нужна реакция только на одно какое-то действие. Если попытаться это корректно прочитать по русски, должно получиться что-то вроде: создай новый экземпляр анонимного класса, который НАСЛЕДУЕТСЯ ОТ КЛАССА MouseAdapter, реализующего нужные тебе интерфейсы и переопредели вот этот метод. Остальные оставляй пустыми, потому что остальные действия можно игнорировать. \\ \hline + +06-35 & Как можно избежать таких многоэтажных и многострочных конструкций и при этом получить понятный код без лишних заморочек? Очень просто. Сказать, что класс, в котором мы в данный момент пишем код - реализует тот или иной интерфейс, благо интерфейсов можно реализовывать сколько угодно, в отличие от наследования от одного единственного родителя, и переопределить все методы. В некоторые из них даже можно написать реализацию, а туда, где требуется интерфейс - передать ссылку на себя самого. Мы же и слушатели мышки и слушатели действий и вообще что хочется. \\ \hline + +06-36 & Отвлечёмся на несколько вопросов 1. Программный интерфейс — это способ 1. рисования графических объектов 2. взаимодействия объектов 3. взаимодействия программы с пользователем + +... 30сек... + +объекты знают за какие ниточки друг друга дёргать именно благодаря интерфейсам, то есть API. конечно же для взаимодействия объектов. 2. Анонимный класс — это класс без чего? 1. без интерфейса 2. без объектов этого класса 3. имени у самого класса + +... 30сек... + +само слово анонимность предполагает неизвестность или полное отсутствие имени, поэтому анонимный класс - это когда без имени. 3. Поле в интерфейсе 1. невозможно создать 2. должно обязательно быть public static final 3. или private final + +... 30сек... + +Как мы могли видеть на одном из слайдов - поля в интерфейсах публичные статические и неизменяемые. И последнее 4. Метод по-умолчанию 1. можно переопределять 2. можно не переопределять 3. можно использовать с полем интерфейса 4. все варианты верны + +... 30сек... + +все варианты верны, метод по умолчанию - это удобство, а не дополнительные ограничения. +\\ \hline + +06-37 & Осталось коротко поговорить о некоторых особенностях работы приложений, использующих графические интерфейсы. \\ \hline + +06-38 & Поскольку графический оконный интерфейс - это всегда многопоточность, да и привычного нам терминала под рукой нет, то тут сразу возникают особенности с обработкой исключений. Как ловить? Как показывать? Вот, например, есть у нас какое-то окно, на котором есть кнопка. У кнопки есть обработчик, в котором что-то идёт не так, скажем, выход за пределы массива. достаточно типичная ситуация. Возникает законный вопрос - как ловить? Посмотрите внимательно на этот слайд, на нём довольно много информации и его надо хорошо проанализировать. Дополнительно обратите внимание, как сделан обработчик - интерфейс слушателя действия реализован объектом класса основного окна и не захламляет конструктор. Если бы мы выбросили такое же исключение в консольном приложении, программа бы завершилась, здесь же мы видим, что несмотря на исключение в консоли окно всё ещё открыто и приложение работает. Если бы в обработчике выбрасывалось исключение, требующее обязательной обработки, всё понятно - обернули в трай кэтч и горя не знаем, но не тут то было, помните, что мы говорили о штатных и нештатных ситуациях? что если в случае исключения программу нужно завершить с исключением? Мы ясно видим, что исключения не завершают приложение. Да и если запускать приложение без среды разработки, куда выведется информация об исключении, в какой терминал, если терминала у пользователя не будет? Куда же можно положить обработчик исключения, чтобы всё точно было хорошо? Как именно мы можем поймать исключение, возникающее где-то в недрах графического фреймворка свинг? Если я поставил вас своими вопросами в тупик - это хорошо, таков был план, пошли разбираться. \\ \hline + +06-39 & Конечно, идеально было бы предварительно поговорить о многопоточности, но это отдельная сложная тема, рассмотрим её чуть позже. Достаточно того, что я уже несколько раз упоминал слово многопоточность в контексте графических интерфейсов и в контексте обработки исключений. Посмотрите пока что на правильный способ создания главных фреймов в свинге, для нас эта конструкция уже не должна быть чем-то сильно магическим, у класса свинг утилит есть статический метод, в который передаётся экземпляр анонимного класса, реализующего интерфейс, и в переопределяемом методе создаётся окно. А пока вы разглядываете эту конструкцию, упомяну ещё раз. Исключение происходит в таком специальном потоке, который называется EDT -- Event Dispathing Thread. Этот поток совершает диспетчеризацию всех событий, происходящих во фреймворке свинг и является фактически генератором других потоков. Метод, который вы видите на экране заставляет объект фрейма не просто создаться, а явно создаёт его именно под управлением ЕДТ. Без этой конструкции тоже будет работать, но документация на свинг утверждает, что правильный способ именно такой. + +Вернуться на слайд назад + +Если внимательно посмотреть на текст исключения внизу экрана, становится видно, что исключение возникло в потоке со странным названием AWT-EventQueue-0. Наличие у потока номера говорит о том, что таких очередей событий у приложения может быть достаточно много, и в каких-то из них могут возникать исключения + +Вернуться обратно вперёд на два +%% 2 + +Подумаем чуть получше, где происходит исключение? в потоке. Как может называться обработчик не пойманных исключений? просто переведём с русского на английский и получим трэд.анкотэксепшнхэндлер. Совершенно внезапно обнаружим возможность реализовать интерфейс именно с таким названием. Интерфейс содержит один метод - непойманное исключение, который принимает на вход поток, в котором произошло исключение и объект исключения, которое произошло. Ну а если серьёзно, то такие обработчики уже написаны и встроены в среду исполнения джава, но они не очень умные, только и умеют, что в консоль писать стектрейс. Но мы то с вами уже крутые программисты, понимаем, что почти любое поведение можно переопределить, в том числе у обработчика исключений потока. +%% 3 + +И вот самое красивое -- в конструкторе на 11й строке устанавливаем для потока обработчик непойманных исключений по-умолчанию, передаём себя, потому что мы и есть обработчик. В самой функции обработки, например, просто выведем на экран модальное окошко с текстом исключения, ронять приложение пока не будем, хоть и можем. Запустив увидим, что в консоли среды разработки прекрасная пустота, а это значит, что мы полностью перехватили контроль над обработкой исключений в этом окне и наша цель достигнута. Всё благодаря интерфейсам. \\ \hline + +06-40 & Подведём некоторые итоги. На этой лекции были рассмотрены программные интерфейсы, что это, зачем они и как работают. Почему с ними неразрывно связано ключевое слово `implements`, как осуществлять Наследование и множественное наследование интерфейсов, как интерфейсы помогают описывать множественное наследование классов, запрещённое в джаве. Реализовали немного интерфейсов, и даже рассмотрели как можно реализовать интерфейсы не полностью. Начали дословно понимать, что же именно написано в этих страшных многоэтажных обработчиках событий и что такое анонимные классы. Напоследок даже обработали одно исключение, возникающее на графическом интерфейсе пользователя. \\ \hline + +06-41 & В качестве домашнего задания нужно полностью разобраться с кодом, написанным на этой лекции, это слишком очевидно, даже не буду считать это за задание, поэтому предлагаю во первых, для приложения с шариками описать появление и убирание шариков по клику мышки левой и правой кнопкой соответственно, при этом пользоваться списками я настоятельно не рекомендую, работу с разного рода коллекциями мы рассмотрим на одной из следующих лекций, во вторых написать, выбросить и обработать такое исключение, которое не позволит создавать более, чем 15 шариков и третье, отмечу его аж двумя звёздочками, тут потребуется немного погуглить - описать ещё одно приложение, в котором на белом фоне будут перемещаться не шарики или квадратики, а изображения формата png, лежащие в виде файла в папке проекта.\\ \hline + +06-42 & Напоследок, соглашаясь с уважаемым древним мудрецом, напомню, что если чувствуете, что материал лекций слишком прост для вас, не ждите, пока станет сложнее, идите и сами изучайте то, что давно хотели, а на лекциях и семинарах мы будем подкладывать и подкладывать под эти знания какой-нибудь хороший фундамент. Развитие - это важно. Всем пока. \\ \hline \end{longtable} -\begin{figure}[H] - \centering - \fontsize{12}{1}\selectfont - \includesvg[scale=1.01]{pics/jd-02-interfaces-use.svg} -\end{figure} - -%\scalebox{.45}{\input{pics/jd-02-bkg-sine.pgf}} - - \begin{forest} - for tree={ - font=\ttfamily, grow'=0, child anchor=west, - parent anchor=south, anchor=west, calign=first, - edge path={ - \noexpand\path [draw, \forestoption{edge}] - (!u.south west) +(7.5pt,0) |- node[fill,inner sep=1.5pt] - {} (.child anchor)\forestoption{edge label}; - }, before typesetting nodes={ - if n=1 {insert before={[,phantom]}} {} }, - fit=band, before computing xy={l=20pt}, - } - [JDKit - [src/ru.gb.jdk.two.online - [bricks - [Brick] - [MainWindow] - ] - [circles - [Background] - [Ball] - [MainWindow] - ] - [common - [Interactable] - [MainCanvas] - [Sprite] - ] - ] - [README.md] - ] - \end{forest} - \end{document} +Тут можно поговорить о лямбдах, для того чтобы сократить синтаксис мы можем просто убрать то что неизменно для этого анонимного класса - название интерфейса, название метода и класс аргумента. -дз -- динамичкески расширяемый массив и слушатели кнопок. подводка: Как известно, в джава все массивы имеют неизменяемую размерность. Это накладывает некоторые архитектурные ограничения на программиста, но мы ж с вами крутые программисты, вон сколько лекций и семинаров позади, можем обмануть систему. Код не сложный, когда старый массив заполнился, просто увеличиваем его в два раза и переносим шарики из старого в новый - - -****** Вернёмся к нашим кружочкам - Смотрим прям первый метод, invokeLater() он принимает на вход какой-то Runnable. Идём в Runnable и видим, что это интерфейс, который реализует один единственный метод run(). Получается, что мы в invokeLater передаём новый экземпляр анонимного класса который РЕАЛИЗУЕТ ИНТЕРФЕЙС Runnable, вот описание этого класса, мы в нём переопределяем метод run. Вот так это читается. Ровно тоже самое мы сделали с mouseListener. Здесь немного сложнее. Есть интерфейс MouseListener в котором описаны вот эти все методы. И есть специальный класс MouseAdapter в котором все эти методы уже реализованы. Реализации пустые, но они есть, поэтому мы можем не все методы оверрайдить, а только те, которые посчитаем нужными. И когда мы этот MouseAdapter отдаём нашему методу, мы говорим: создай нам новый экземпляр анонимного класса, который НАСЛЕДУЕТСЯ ОТ КЛАССА MouseAdapter и переопредели вот этот метод. Остальные оставляй пустыми. Чувствуете разницу? Как можно избежать таких конструкций и при этом получить понятный код без лишних заморочек? Очень просто. Скажем, что наш класс - реализует тот или иной интерфейс, и переопределим все методы. В некоторые из них даже напишем реализацию, и туда, где требуется интерфейс - передадим себя. Мы же теперь MouseListener, да и Runnable. - - - исключения - 06-29 & Осталось коротко поговорить о некоторых особенностях работы приложений, использующих графические интерфейсы. \\ \hline - -06-30 & Поскольку графический оконный интерфейс - это всегда многопоточность, да и привычного нам терминала под рукой нет, то тут сразу возникают особенности с обработкой исключений. Как ловить? Как показывать? Вот, например, есть у нас какое-то окно, на котором есть кнопка. У кнопки есть обработчик, в котором что-то идёт не так, скажем, выход за пределы массива. достаточно типичная ситуация. Как - - -Аннотации? \ No newline at end of file +раннее, позднее связывание diff --git a/scenarios/jtd3-08b.tex b/scenarios/jtd3-08b.tex new file mode 100644 index 0000000..9847f81 --- /dev/null +++ b/scenarios/jtd3-08b.tex @@ -0,0 +1,23 @@ +\documentclass[../j-spec.tex]{subfiles} + +\begin{document} +\section{Интерфейсы} +\begin{longtable}{|p{35mm}|p{135mm}|} +\hline +Экран & Слова \\ \hline +\endhead + +Титул & Здравствуйте, добро пожаловать на курс посвящённый инструментарию разработчика на джава \\ \hline + +Отбивка & в сегодняшней лекции коснёмся одного из ключевых понятий программирования на языке джава -- обобщённого программирования. \\ \hline + +На прошлом уроке & На прошлом уроке мы поговорили об интерфейсах, рассмотрели понятие и принцип работы, поговорили о ключевом слове implements; коротко посмотрели на наследование и множественное наследование интерфейсов, реализацию, значения по умолчанию и частичная реализацию интерфейсов. Буквально два слова я сказал о функциональных интерфейсах и чуть подробнее об анонимных классах. \\ \hline + +На этом уроке & Поговорим \\ \hline + + & \\ \hline + + +\end{longtable} + +\end{document}