JavaRush/Курсы/Java Core/Интерфейсы

Интерфейсы

Открыта

— Привет, Амиго! Сегодня у тебя день открытий. Новая и интересная тема – это интерфейсы.

— Ага. День настолько чудесный, что я приду домой и приму ванну полную воды.

— Интерфейс – это дитя Абстракции и Полиморфизма. Интерфейс очень напоминает абстрактный класс, у которого все методы абстрактные. Он объявляется так же, как и класс, только используется ключевое слово interface. Примеры:

Код Описание и Факты
interface Drawable {
    void draw();
}
interface HasValue {
    int getValue();
}
1) Вместо слова class пишем interface.

2) Содержит только абстрактные методы (слово abstract писать не нужно).

3) На самом деле у интерфейсов все методы — public.

interface Element extends Drawable, HasValue {
    int getX();
    int getY();
}
Интерфейс может наследоваться только от интерфейсов.

Интерфейсов-родителей может быть много.

abstract class ChessItem implements Drawable, HasValue {
    private int x, y, value;

    public int getValue() {
        return value;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

}
Класс может наследоваться от нескольких интерфейсов (и только от одного класса). При этом используется ключевое слово implements.

Класс ChessItem объявлен абстрактным: он реализовал все унаследованные методы, кроме draw.

Т.е. класс ChessItem содержит один абстрактный метод: draw().

— Интересно. А зачем нужны интерфейсы? Когда их используют?

— У интерфейсов есть два сильных преимущества по сравнению с классами:

1) Отделение «описания методов» от их реализации.

Раньше я тебе рассказывал, что если ты хочешь разрешить вызывать методы своего класса из других классов, то их нужно пометить ключевым словом public. Если же хочешь, чтобы какие-то методы можно было вызывать только из твоего же класса, их нужно помечать ключевым словом private. Другими словами мы делим методы класса на две категории: «для всех» и «только для своих».

С помощью интерфейсов, это деление можно усилить еще больше. Мы сделаем специальный «класс для всех», и второй «класс для своих», который унаследуем от первого. Вот как это примерно будет:

Было
class Student {
    private String name;

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    private void setName(String name) {
        this.name = name;
    }
Стало
interface Student {
    public String getName();
}

class StudentImpl implements Student {
    private String name;
    public StudentImpl(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
    private void setName(String name) {
        this.name = name;
    }
}
Было
public static void main(String[] args) {
    Student student =
        new Student("Alibaba");
    System.out.println(student.getName());
}
Стало
public static void main(String[] args) {
    Student student =
        new StudentImpl("Ali");
    System.out.println(student.getName());
}

Мы разбили наш класс на два: интерфейс и класс, унаследованный от интерфейса.

— И в чем тут преимущество?

— Один и тот же интерфейс могут реализовывать (наследовать) различные классы. И у каждого может быть свое собственное поведение. Так же как ArrayList и LinkedList – это две различные реализации интерфейса List.

Таким образом, мы скрываем не только различные реализации, но и даже сам класс, который ее содержит (везде в коде может фигурировать только интерфейс). Это позволяет очень гибко, прямо в процессе исполнения программы, подменять одни объекты на другие, меняя поведение объекта скрытно от всех классов, которые его используют.

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

2) Множественное наследование.

В Java все классы могут иметь только одного класса-родителя. В других языках программирования, классы часто могут иметь несколько классов-родителей. Это очень удобно, но приносит так же много проблем.

В Java пришли к компромиссу – запретили множественное наследование классов, но разрешили множественное наследование интерфейсов. Интерфейс может иметь несколько интерфейсов-родителей. Класс может иметь несколько интерфейсов-родителей и только один класс-родитель.

Комментарии (329)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Grigoryvvv
Уровень 28
Expert
9 августа, 10:25
09.08.2026 / 22 уровень
SUNSHINE
Уровень 30
31 марта, 14:48
Тут написано, что интерфейсы содержат только абстрактные методы, но это уже давно неправда. У интерфейсов могут быть дефолтные методы - реализованные методы, но обязаны помечаться ключевым словом default.
Rei
Уровень 32
23 февраля, 08:11
Прям хождение по кругам сансары
Сергей
Уровень 42
24 августа 2025, 11:41
Я В ЭТИ ИГРЫ УЖЕ ИГРАЛ!!!
Anonymous #3585174
Уровень 33
4 августа 2025, 07:39
Like
j1nDo
Уровень 29
7 августа 2024, 12:52
ПОВТОРЕНИЕ - МАТЬ УЧЕНИЯ
Wren
Уровень 29
20 августа 2024, 13:37
СТРАДАНИЯ ЗАКАЛЯЮТ ХАРАКТЕР
C0N5P1RACY QA Automation Engineer
24 января, 19:38
ЧЕРЕЗ БОЛЬ К РОСТУ
Igoreek
Уровень 43
1 августа 2024, 08:07
Тут был Йа
Vlad
Уровень 30
2 августа 2024, 05:50
Неуловимый Игорёк. 2 лвла за день.
{Java_Shark}
Уровень 36
16 июля 2024, 14:15
++
Igoreek
Уровень 43
1 августа 2024, 08:07
зачем ты ставишь ++ под каждой лекцией?
Vlad
Уровень 30
2 августа 2024, 05:50
Это его фишка
{Java_Shark}
Уровень 36
7 августа 2024, 09:11
секрет)))
CoreOne
Уровень 23
Expert
1 сентября 2024, 08:38
инкрементирует свой лвл))
shakh
Уровень 33
28 сентября 2024, 12:04
Он ставит ++ там, где инфа повторяется
Exaltyr777
Уровень 25
30 августа 2025, 17:24
чтобы понять не подсунули ли опять лекцию которую уже читал 2 недели назад😁
Илья
Уровень 26
14 июля 2024, 11:32
В примере с интерфейсом Student
interface Student
{
 public String getName();
}

class StudentImpl implements Student
{
 private String name;
 public StudentImpl(String name)
 {
  this.name = name;
 }
 public String getName()
 {
  return this.name;
 }
Класс Student
class Student
{
 private String name;

 public Student(String name)
 {
  this.name = name;
 }

 public String getName()
 {
  return this.name;
 }
Разница вообще минимальная. Не понял. В чем преимущество?
mrnght
Уровень 28
20 июля 2024, 03:50
преимущество будет видно, если мы, например, создадим список с объектами разных классов, но все они будут унаследованы от интерфейса Student. Без него мы бы не смогли такой список создать.
Semen Semenov
Уровень 37
28 марта 2024, 09:25
Почему класс ChessItem на приведенном примере не имплементирует интерфейс Element и при этом реализует его методы? Объясните, пожалуйста.
2 апреля 2024, 22:22
тоже интересует этот вопрос, опечатка?
HOCOK_B_CMETAHE QA Automation Engineer
13 мая 2024, 23:31
В данном случае класс ChessItem не реализует методы интерфейса Element, а объявляет свои, хоть это и не обязательно.
Bohdan
Уровень 13
2 июня 2024, 11:01
Ну хз, написано ведь он реализовал все унаследованные методы, кроме draw, а значит не один лишь getValue