Default и Static методы в интерфейсах
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy. Урок 37 из 87.
Изначально interface могли содержать только abstract method без реализации. Начиная с Java 8, interface получили возможность включать default method и static method, что сделало их более гибкими.
default method предоставляет реализацию непосредственно в interface с использованием ключевого слова default. Классы, которые реализуют interface, автоматически наследуют это behavior, но могут выполнить override, если это needed:
public interface Drawable {
void draw();
default void display() {
System.out.println("Displaying on screen...");
draw();
}
}Любой класс, реализующий Drawable, бесплатно получает метод display(). Это особенно полезно для добавления новых методов в существующие интерфейсы без нарушения работы классов, которые уже их реализуют.
Статические методы в интерфейсах работают так же, как статические методы в классах. Они принадлежат самому интерфейсу и вызываются с использованием имени интерфейса:
public interface MathOperations {
static int add(int a, int b) {
return a + b;
}
}
// Использование
int result = MathOperations.add(5, 3);Статические методы interface нельзя переопределить, и они не наследуются классами, которые реализуют interface. Они полезны для служебных методов, связанных с назначением interface.
Если class implements два interface с одинаковой сигнатурой default method, class должен override этот method, чтобы разрешить конфликт.
Задание
ЛегкоДавайте создадим систему обмена сообщениями, демонстрирующую как default, так и static методы в интерфейсах. Вы создадите интерфейс со встроенной функциональностью, которую реализующие его классы смогут использовать напрямую или при необходимости настраивать.
Вы организуете код в четырёх файлах:
Messenger.java: Define интерфейс, представляющий любую службу обмена сообщениями. Он должен Declare abstract methodsendMessage(String message), возвращающий void. Add default method с именемsendWithTimestamp(String message), который выводит:[TIMESTAMP], а затем вызываетsendMessage(message). Также включите static method с именемformatMessage(String message), который возвращает message, converted в верхний регистр.EmailMessenger.java: Create класс, который implementsMessenger. У него естьrecipientfield типа String. Включите constructor для инициализации recipient. ImplementsendMessage(), чтобы вывести:Email to [recipient]: [message]. Этот класс использует defaultsendWithTimestamp()method как есть.SMSMessenger.java: Create ещё один класс, который implementsMessenger. У него естьphoneNumberfield типа String. Включите constructor для инициализации номера телефона. ImplementsendMessage(), чтобы вывести:SMS to [phoneNumber]: [message]. Override defaultsendWithTimestamp()method, чтобы вывести:[URGENT], а затем вызватьsendMessage(message)вместо использования поведения default timestamp.Main.java: Объедините всё, чтобы продемонстрировать default и static методы интерфейса. Вы получите три inputs: email recipient, phone number и message. Сначала используйте static methodMessenger.formatMessage(), чтобы отформатировать message и сохранить его. Затем Create EmailMessenger и SMSMessenger. Для каждого messenger вызовитеsendWithTimestamp()с formatted message: обратите внимание, как EmailMessenger использует default implementation, тогда как SMSMessenger использует свою переопределённую версию.
Вы получите три inputs: email recipient (String), phone number (String) и message (String).
В вашем output должно быть всего четыре строки: по две для каждого messenger: строка с префиксом ([TIMESTAMP] или [URGENT]), за которой следует строка с message. EmailMessenger покажет default timestamp prefix, тогда как SMSMessenger покажет свой custom urgent prefix. Оба будут использовать message, отформатированное static method (в верхнем регистре)!
Попробуйте сами
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Прочитать входные данные
String emailRecipient = scanner.nextLine();
String phoneNumber = scanner.nextLine();
String message = scanner.nextLine();
// TODO: Используйте Messenger.formatMessage() для форматирования сообщения и сохраните его
// TODO: Создайте EmailMessenger с получателем электронной почты
// TODO: Создайте SMSMessenger с номером телефона
// TODO: Вызовите sendWithTimestamp() у EmailMessenger с отформатированным сообщением
// TODO: Вызовите sendWithTimestamp() у SMSMessenger с отформатированным сообщением
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»Потренируйтесь самостоятельно: Онлайн-компилятор Java