Интерфейсы, enum и связи объектов в Java. Практические Задания
Добавьте константе SUMMER собственное тело, чтобы переопределить getDescription(), — и Season.SUMMER.getClass() внезапно вернёт не Season, а анонимный класс Season$1. Именно на таких нюансах интерфейсов и перечислений чаще всего спотыкаются, и именно их удобнее всего прочувствовать на практике.
System.out.println(Season.SUMMER.getClass()); // class Season$1
System.out.println(Season.SUMMER.getDeclaringClass()); // class Season На этой странице собраны 4 практических задания по Java на темы интерфейсы, оператор instanceof и преобразование ссылочных типов, перечисления (enum) с полями, конструкторами и переопределёнными методами, абстрактные классы и наследование. Задания идут от простого к сложному: от одного интерфейса Printable до мини-приложения «интернет-магазин». К каждой задаче есть решение на Patreon, к первым двум — ещё и видеоразбор.
Какие темы понадобятся
Перед решением стоит повторить теорию по интерфейсам в Java, перечислениям и преобразованию ссылочных типов.
| Задание | Темы | Что тренирует |
|---|---|---|
| 1. Printable | Интерфейс, массив интерфейсного типа, instanceof, статические методы | Полиморфизм: один вызов print() — разное поведение |
| 2. Времена года | enum, поле и конструктор перечисления, switch, переопределение метода в константе | Перечисление как полноценный класс |
| 3. Одежда | enum, абстрактный класс, наследование, реализация нескольких интерфейсов | Проектирование иерархии классов |
| 4. Интернет-магазин | Всё вышеперечисленное + ввод с клавиатуры, enum для операций меню | Сборка небольшого приложения целиком |
Интерфейс Printable
- Определить интерфейс
Printable, содержащий методvoid print(). - Определить класс
Book, реализующий интерфейсPrintable. - Определить класс
Magazine, реализующий интерфейсPrintable. - Создать массив типа
Printable, который будет содержать книги и журналы. - В цикле пройти по массиву и вызвать метод
print()для каждого объекта. - Создать статический метод
printMagazines(Printable[] printable)в классеMagazine, который выводит на консоль названия только журналов. - Создать статический метод
printBooks(Printable[] printable)в классеBook, который выводит на консоль названия только книг. Используем оператор instanceof.
Подсказка
Начиная с Java 16, после instanceof можно сразу объявить переменную нужного типа (pattern matching): if (p instanceof Magazine magazine) { System.out.println(magazine.getTitle()); }. Явное приведение (Magazine) p в этом случае не нужно. Попробуйте решить задачу обоими способами.
Видеоразбор решения →Решение на Patreon →
Времена года (enum)
- Создать перечисление
Season, содержащее времена года:WINTER,SPRING,SUMMER,AUTUMN. - Создать переменную, содержащую ваше любимое время года, и распечатать всю информацию о нём: имя константы (
name()), порядковый номер (ordinal()), результатtoString(). - Создать метод, который принимает на вход переменную созданного вами enum-типа. Если значение равно
SUMMER, выводим на консоль «Я люблю лето», и так далее для каждого времени года. Используем операторswitch. - Перечисление должно содержать поле со средней температурой для каждого времени года.
- Добавить конструктор, принимающий на вход среднюю температуру.
- Создать метод
getDescription(), возвращающий строку «Холодное время года». Переопределить методgetDescription()для константыSUMMER— он должен возвращать «Тёплое время года». - В цикле по
Season.values()распечатать все времена года, среднюю температуру и описание времени года.
Современный вариант switch
Кроме классического switch с break, пункт 3 можно решить switch-выражением (Java 14+). Если перечислены все константы enum, ветка default не нужна — компилятор сам проверит полноту.
String text = switch (season) {
case WINTER -> "Я люблю зиму";
case SPRING -> "Я люблю весну";
case SUMMER -> "Я люблю лето";
case AUTUMN -> "Я люблю осень";
};
System.out.println(text);Видеоразбор решения →Решение на Patreon →
Одежда
- Создать перечисление
ClothingSize, содержащее размеры одежды:XXS,XS,S,M,L.- Перечисление содержит числовое поле
euroSize(32, 34, 36, 38, 40), соответствующее каждому размеру, и конструктор, принимающий на входeuroSize. - Перечисление содержит метод
getDescription(), возвращающий строку «Взрослый размер». Переопределить методgetDescription()для константыXXS— он должен возвращать строку «Детский размер».
- Перечисление содержит числовое поле
- Создать интерфейсы «Мужская одежда» (
MenClothing) с методом «одеть мужчину» (dressMan()) и «Женская одежда» (WomenClothing) с методом «одеть женщину» (dressWoman()). - Создать абстрактный класс «Одежда» (
Clothes), содержащий поля: размер одежды (ClothingSize), стоимость, цвет. - Создать классы-наследники класса
Clothes:- Футболка (
TShirt) — реализует интерфейсыMenClothingиWomenClothing; - Брюки (
Pants) — реализуют интерфейсыMenClothingиWomenClothing; - Юбка (
Skirt) — реализует интерфейсWomenClothing; - Галстук (
Tie) — реализует интерфейсMenClothing.
- Футболка (
- Создать массив, содержащий все типы одежды. Создать класс «Ателье» (
Atelier) с методамиdressWoman(Clothes[] clothes)иdressMan(Clothes[] clothes), на вход которым поступает этот массив. МетодdressWomanвыводит на консоль всю информацию о женской одежде, методdressMan— о мужской. Отбирайте нужную одежду с помощьюinstanceof.
Неочевидный момент
Конструктор перечисления всегда неявно private: объявить его public или protected нельзя, а вызвать через new ClothingSize(32) — тоже. Константы создаются один раз при загрузке класса. И ещё о стиле: Java разрешает кириллицу в именах классов и методов, но в реальных проектах используют только латиницу — поэтому в условии указаны английские идентификаторы.
Вход по логину, каталог и покупка через enum и switch
Интернет-магазин · часть 2 из 11 · ← часть 1 · часть 3 →
Продолжаем мини-приложение «интернет-магазин» (часть 1). Должны быть реализованы следующие возможности:
- Аутентификация пользователя: пользователь вводит логин и пароль с клавиатуры (например, через
Scanner). - Просмотр списка каталогов товаров.
- Просмотр списка товаров определённого каталога.
- Добавление выбранного товара в корзину.
- Покупка товаров, находящихся в корзине.
Создайте перечисление, содержащее значения для перечисленных операций, и выбирайте нужное действие через switch по этому перечислению. Можете добавить свои операции или изменить что-то на свой вкус.
При написании программ обращайте внимание на рекомендации по оформлению кода.
Часто задаваемые вопросы
Что такое интерфейс в Java и чем он отличается от абстрактного класса?
Интерфейс в Java — это контракт: набор методов, которые обязан реализовать класс. Поля интерфейса всегда public static final (константы), а с Java 8 в нём могут быть default- и static-методы, с Java 9 — private-методы. Абстрактный класс, в отличие от интерфейса, может хранить состояние (обычные поля) и иметь конструкторы. Главное практическое различие: класс может реализовать сколько угодно интерфейсов, но наследовать только один класс.
Может ли enum реализовать интерфейс или наследоваться от класса?
Реализовать интерфейс — да, например enum Season implements Printable, причём каждая константа может реализовать метод по-своему. Наследоваться от другого класса — нет: любой enum неявно наследует java.lang.Enum, а множественного наследования классов в Java нет. Унаследовать свой класс от enum тоже нельзя.
Что будет, если класс реализует два интерфейса с одинаковым default-методом?
Код не скомпилируется, пока класс сам не переопределит этот метод. Внутри переопределения можно явно выбрать нужную реализацию, например MenClothing.super.info(). Если же совпадающие методы в обоих интерфейсах абстрактные, конфликта нет — достаточно одной реализации в классе.
Как правильно писать метки case в switch по enum?
Традиционно в метке указывают только имя константы: case SUMMER, без имени типа. Запись case Season.SUMMER до Java 21 вызывала ошибку компиляции, с Java 21 квалифицированное имя разрешено. В switch-выражении (Java 14+) нужно покрыть все константы перечисления либо добавить default, иначе код не скомпилируется.
Комментарии