Menu
Coddy logo textTech

Default и Static методы в интерфейсах

Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 37 из 87.

Изначально интерфейсы могли содержать только абстрактные методы без реализации. Начиная с Java 8, интерфейсы получили возможность включать методы по умолчанию и статические методы, что сделало их более гибкими.

Метод по умолчанию предоставляет реализацию непосредственно в интерфейсе с использованием ключевого слова default. Классы, реализующие интерфейс, автоматически наследуют это поведение, но при необходимости могут его переопределить:

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);

Статические методы интерфейса не могут быть переопределены и не наследуются реализующими классами. Они полезны для вспомогательных методов, связанных с назначением интерфейса.

Если класс реализует два интерфейса с одинаковой сигнатурой метода по умолчанию, класс должен переопределить этот метод, чтобы разрешить конфликт.

challenge icon

Задание

Легко

Давайте создадим систему обмена сообщениями, которая демонстрирует использование методов по умолчанию (default) и статических (static) методов в интерфейсах. Вы создадите интерфейс со встроенной функциональностью, которую реализующие классы смогут использовать напрямую или настраивать по мере необходимости.

Вы организуете свой код в четырех файлах:

  • Messenger.java: Определите интерфейс, представляющий любую службу обмена сообщениями. Он должен объявлять абстрактный метод sendMessage(String message), который возвращает void. Добавьте метод по умолчанию с именем sendWithTimestamp(String message), который выводит: [TIMESTAMP] , после чего вызывает sendMessage(message). Также включите статический метод с именем formatMessage(String message), который возвращает сообщение, преобразованное в верхний регистр.
  • EmailMessenger.java: Создайте класс, реализующий Messenger. У него есть поле recipient (String). Включите конструктор для инициализации получателя. Реализуйте sendMessage() для вывода: Email to [recipient]: [message]. Этот класс использует метод по умолчанию sendWithTimestamp() как есть.
  • SMSMessenger.java: Создайте еще один класс, реализующий Messenger. У него есть поле phoneNumber (String). Включите конструктор для инициализации номера телефона. Реализуйте sendMessage() для вывода: SMS to [phoneNumber]: [message]. Переопределите метод по умолчанию sendWithTimestamp(), чтобы он выводил: [URGENT] , а затем вызывал sendMessage(message) вместо использования поведения по умолчанию с меткой времени.
  • Main.java: Объедините все вместе, чтобы продемонстрировать методы интерфейса по умолчанию и статические методы. Вы получите три входных значения: получателя электронной почты, номер телефона и сообщение. Сначала используйте статический метод Messenger.formatMessage(), чтобы отформатировать сообщение и сохранить его. Затем создайте EmailMessenger и SMSMessenger. Для каждого мессенджера вызовите sendWithTimestamp() с отформатированным сообщением — обратите внимание, как EmailMessenger использует реализацию по умолчанию, в то время как SMSMessenger использует свою переопределенную версию.

Вы получите три входных значения: получателя электронной почты (String), номер телефона (String) и сообщение (String).

Ваш вывод должен содержать всего четыре строки — по две для каждого мессенджера. EmailMessenger покажет префикс метки времени по умолчанию, а SMSMessenger покажет свой собственный префикс срочности. Оба будут использовать статически отформатированное сообщение (в верхнем регистре)!

Шпаргалка

Начиная с Java 8, интерфейсы могут включать методы по умолчанию и статические методы в дополнение к абстрактным методам.

Методы по умолчанию предоставляют реализацию непосредственно в интерфейсе с использованием ключевого слова default. Классы, реализующие интерфейс, наследуют это поведение автоматически, но при необходимости могут его переопределить:

public interface Drawable {
    void draw();
    
    default void display() {
        System.out.println("Displaying on screen...");
        draw();
    }
}

Статические методы в интерфейсах принадлежат самому интерфейсу и вызываются с использованием имени интерфейса. Они не могут быть переопределены и не наследуются реализующими классами:

public interface MathOperations {
    static int add(int a, int b) {
        return a + b;
    }
}

// Использование
int result = MathOperations.add(5, 3);

Если класс реализует два интерфейса с одинаковой сигнатурой метода по умолчанию, класс должен переопределить этот метод, чтобы разрешить конфликт.

Попробуйте сами

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 с отформатированным сообщением
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование