Урок 10

Интерфейсы


1. Что такое интерфейс?

Интерфейс это конструкция языка Java, в рамках которой могут описываться только абстрактные публичные (abstract public) методы и статические константы (final static).

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

Интерфейсы не способны сохранять данные состояния.

Интерфейсы позволяют в полной мере использовать принцип полиморфизма "один интерфейс, несколько методов". 

Что такое интерфейс?

Интерфейсы могут быть c модификатором public или default.

Переменные интерфейса являются public static final по умолчанию и эти модификаторы необязательны.

Все методы интерфейса являются public abstract и эти модификаторы необязательны. Объявляемые методы не содержат тел. Их объявления завершаются точкой с запятой. По существу, они являются абстрактными методами.

Пример 1. Интерфейс

public interface Moveable {
    int RIGHT = 1;
    int LEFT = 2;
    int UP = 3;
    int DOWN = 4;

    void moveRight();

    void moveLeft();
}

Чтобы реализовать интерфейс, в классе должен быть создан полный набор методов, определенных в этом интерфейсе. Но в каждом классе могут быть определены особенности собственной реализации данного интерфейса.

Пример 2. Класс реализующий Moveable интерфейс

public class Transport implements Moveable {
    public void moveRight() {
        System.out.println("Transport moving right");
    }

    public void moveLeft() {
        System.out.println("Transport moving left");
    }

    public void stop() {
        System.out.println("Transport stopping");
    }

    public void start() {
        System.out.println("Transport starting");
    }
}

Один интерфейс может быть реализован любым количеством классов.

Один интерфейс может быть реализован любым количеством классов

Переменные можно объявлять как ссылки на объекты, в которых используется тип интерфейса, а не тип класса. На основе интерфейсов нельзя порождать объекты.

Пример 3. Создание объектов класса реализующего Moveable интерфейс

public class TransportDemo {
    public static void main(String[] args) {
        Moveable moveable = new Transport();
        Transport transport = new Transport();
        Moveable robot = new Robot();
        //Moveable moveable1 =new Moveable();

        //  moveable.start();
        moveable.moveRight();
        moveable.moveLeft();
        System.out.println();

        transport.start();
        transport.moveRight();
        transport.moveLeft();
        transport.stop();
        System.out.println();

        robot.moveLeft();
        robot.moveRight();
    }
}

Если класс реализует интерфейс, но не полностью реализует определенные в нем методы , он должен быть объявлен как abstract:

Пример 4. Класс не полностью реализующий интерфейс

public abstract class Device implements Moveable {
    public void moveRight() {
        System.out.println("Device moving right");
    }
}

Один класс может реализовать любое количество интерфейсов:

Один класс может реализовать любое количество интерфейсов.

Пример 5. 

public interface CargoAuto {
    void transportCargo();
}
public interface PassengersAuto {
    void transportPassengers();
}
public class Truck implements CargoAuto {
    public void transportCargo() {
        System.out.println("Везу груз");
    }
}
public class Pickup implements CargoAuto, PassengersAuto {
    public void transportCargo() {
        System.out.println("Везу груз");
    }

    public void transportPassengers() {
        System.out.println("Везу пассажиров");
    }
}
public class Sedan implements PassengersAuto {
    public void transportPassengers() {
        System.out.println("Везу пассажиров");
    }
}

2. Вложенные интерфейсы

Интерфейсы могут вкладываться в классы и в другие интерфейсы:

Пример 6. Вложенный интерфейс

public class A {
    public interface NestedIf {
        boolean isNotNegative(int x);
    }
}
public class B implements A.NestedIf {
    public boolean isNotNegative(int x) {
        return x >= 0;
    }
}
public class NestedIfDemo {
    public static void main(String[] args) {
        A.NestedIf nif = new B();
        if (nif.isNotNegative(10)) {
            System.out.println("Число 10 не отрицательное.");
        }
        if (nif.isNotNegative(-12)) {
            System.out.println("Этo не будет выведено.");
        }
    }
}

3. Расширение интерфейсов

Интерфейс может наследоваться от другого интерфейса через ключевое слово extends:

Пример 7. Расширение интерфейсов

Расширение интерфейсов

public interface Sport {
    void setHomeTeam(String name);

    void setVisitingTeam(String name);
}
public interface Hockey extends Sport {
    void homeGoalScored();

    void visitingGoalScored();

    void endOfPeriod(int period);

    void overtimePeriod(int ot);
}
public interface TVProgram {
    void switchToChannel();
}
public interface Football extends Sport, TVProgram {
    void homeTeamScored(int points);

    void visitingTeamScored(int points);

    void endOfQuarter(int quarter);
}
public class FootballImpl implements Football {
    @Override
    public void setHomeTeam(String name) {
        System.out.println("Setting Home Team");
    }

    @Override
    public void switchToChannel() {
        System.out.println("Switching to channel");
    }

    @Override
    public void homeTeamScored(int points) {
        System.out.println("Scored");
    }

    @Override
    public void setVisitingTeam(String name) {
        System.out.println("Setting visiting team");
    }

    @Override
    public void visitingTeamScored(int points) {
        System.out.println("Visiting Team Scored");
    }

    @Override
    public void endOfQuarter(int quarter) {
        System.out.println("End of quarter");
    }
}

4. Интерфейсы маркеры

Это интерфейсы, реализация которых автоматически придает классу определенные свойства. К последним относятся, например, интерфейсы Cloneable и Serializable, отвечающие за клонирование и сохранение объекта в информационном потоке соответственно.

5. Методы по умолчанию

Начиная с версии JDК 8 методы можно объявлять в интерфейсе с реализацией по умолчанию, т.е. указать его поведение. Другое название - методы расширения.

Причины для внедрения методов по умолчанию:

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

Пример 8. Пример определения метода по умолчанию в интерфейсе

public interface SomeInterface {
    default String defaultMethod() {
        return "Объект типа String по умолчанию";
    }
}
public class SomeInterfaceImpl1 implements SomeInterface {
}
public class SomeInterfaceImpl2 implements SomeInterface {
    @Override
    public String defaultMethod() {
        return "Другая символьная строка";
    }
}
public class DefaultMethodDemo {
    public static void main(String[] args) {
        SomeInterface obj1 = new SomeInterfaceImpl1();
        SomeInterface obj2 = new SomeInterfaceImpl2();

        System.out.println(obj1.defaultMethod());

        System.out.println(obj2.defaultMethod());
    }
}

6. Статические методы в интерфейсе

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

Для вызова статического метода достаточно указать имя интерфейса и через точку имя самого метода.

Пример 9.  Статический метод в интерфейсе

public interface MyIf {
    int getNumber();

    static int staticMethod() {
        return 0;
    }
}
public class StaticMethodDemo {
    public static void main(String[] args) {
        MyIf obj1 = new MyIfImp();

        System.out.println(obj1.getNumber());
        System.out.println(MyIf.staticMethod());
    }
}


0 comments
Leave your comment: