назначение интерфейса в java [дубликат]

127
11 января 2021, 11:50
На этот вопрос уже даны ответы здесь:
Интерфейсы в ООП (Java), по-простому? (16 ответов)
Закрыт 1 год назад.

привожу пример из некоего сайта:

public interface Swimmable  {
     public void swim();
}
public class Duck implements Swimmable {
    public static void main(String[] args) {
        Duck duck = new Duck();
        duck.swim();
    }
    public void swim() {
        System.out.println("Уточка, плыви!");
    }
}

для чего нужен interface если можно просто:

public class Duck {
  public static void main(String[] args) {
    Duck duck = new Duck();
    duck.swim();
  }
  public void swim() {
    System.out.println("Уточка, плыви!");
  }
}

с тем же результатом

Answer 1

Полагаю, что Alexey имел ввиду следующее: Возможно автор кода предполагал, что ему понадобится ещё какой-нибудь класс, в котором нужен будет метод swim(). То есть если у вас есть много классов (пусть рыба, утка, черепаха, лебедь), то у всех их будет общий метод swim(). В таком случае принято создавать интерфейс, чтобы показать, что у каждого из данных классов есть методы из созданного интерфейса.

Answer 2

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

Значит, мы не можем сделать метод swim в классе животное, от которого наследуются птицы, рыбы и млекопитающие, не можем также сделать такой метод в классах птица и млекопитающее. Однако мы можем захотеть иметь список разных плавающих животных и заставить их всех по очереди плавать, даже если не знаем, к какому конкретному классу относится очередное животное. Выражаясь по-умному, нужно обеспечить полиморфизм между объектами, относящимися к различным иерархиям наследования.

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

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

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

import java.util.ArrayList;
import java.util.List;
public class AnimalFarm {
  interface Swimming { // Все, кто реализует этот интерфейс, должны уметь плавать 
    public void swim(); 
  }
  abstract class Animal { // Все животные едят 
    abstract public void eat() ; 
  }
  abstract class Bird extends Animal {
    abstract public void fly() ; // Птицы еще умеют летать
    abstract public void layEggs() ; // и откладывать яйца
  }
  abstract class Mammal extends Animal {
    abstract public void bearAYoung() ; // Млекопитающие рожают детенышей
  }
  abstract class Fish extends Animal implements Swimming { // Все рыбы умеют плавать
    abstract public void spawn() ; // А еще мечут икру
  }
  class Duck extends Bird implements Swimming { // Утка умеет плавать
    @Override public void eat() { System.out.println("The Duck is eating"); } 
    @Override public void fly() { System.out.println("The Duck is flying"); };
    @Override public void layEggs() { System.out.println("The Duck is laying eggs"); };
    @Override public void swim() { System.out.println("The Duck is swimming"); };; 
  }
  class Hen extends Bird { // Курица не умеет плавать
    @Override public void eat() { System.out.println("The Duck is eating"); } 
    @Override public void fly() { System.out.println("The Duck is flying"); };
    @Override public void layEggs() { System.out.println("The Duck is laying eggs"); };
  }
  class Dolphin extends Mammal implements Swimming { // Дельфин умеет плавать
    @Override public void eat() { System.out.println("Дельфин ест рыбу"); }; 
    @Override public void bearAYoung() { System.out.println("Дельфин рожает дельфиненка"); };
    @Override public void swim() { System.out.println("Дельфин плывет"); }; 
  }
  class Cat extends Mammal { // Кошка не умеет плавать
    @Override public void eat() { System.out.println("Кошка ест мышку"); }; 
    @Override public void bearAYoung() { System.out.println("Кошка рожает котенка"); };
  }
  class Salmon extends Fish { // Лосось -- рыба, значит, умеет плавать
    @Override public void eat() { System.out.println("Лосось ест не знаю что"); }; 
    @Override public void swim() { System.out.println("Лосось плывет"); }; 
    @Override public void spawn() { System.out.println("Лосось мечет икру"); };
  }
  private void run () {
    List<Swimming> waterDwellers = new ArrayList<>(); // Вместо класса указываем интерфейс
    waterDwellers.add(new Salmon());    // Рыбы,  
    waterDwellers.add(new Duck());    // Птицы, умеющие плавать
    waterDwellers.add(new Dolphin()); // Млекопитающие, умеющие плавать 
    for (Swimming animal: waterDwellers) { //
        animal.swim();                              // Все умеют плавать
    }
  }
  public static void main(String... args) {
    new AnimalFarm().run();
  }
}

Ну и всё-таки читайте учебники, у Шилдта и Экеля всё это очень хорошо описано.

Answer 3

Вам нужно понять, что вам нужно - Duck или Swimmable. Думаю согласитесь, что это разные функциональные сущности. Если в вашей программе будет нужен именно Swimmable, то вы и создаете интерфейс для этих целей.

READ ALSO
Как правильно внедрить проект C++ в Android?

Как правильно внедрить проект C++ в Android?

Такая история, у меня есть проект написаный на C++, который компилируется и работает

136
Коллекция в контроллере

Коллекция в контроллере

В коллекцию через ajax приходят данные в ListКак правильно их обработать и передать в метод? Спасибо! Контроллер:

106
Как в OSGI (Apache Felix) внедрить АОП для чужих bundle?

Как в OSGI (Apache Felix) внедрить АОП для чужих bundle?

Есть необходимость добавить АОП для классов из разных бандлов в OSGI (Apache Felix)

86
Как различать объекты в RecyclerView?

Как различать объекты в RecyclerView?

Я могу повеcить слушатель на RecyclerView но тогда все предметы будут выполнять одинаковые команды, мне надо чтобы отдельный объект выполнял отдельную...

113