привожу пример из некоего сайта:
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("Уточка, плыви!");
}
}
с тем же результатом
Полагаю, что Alexey имел ввиду следующее: Возможно автор кода предполагал, что ему понадобится ещё какой-нибудь класс, в котором нужен будет метод swim(). То есть если у вас есть много классов (пусть рыба, утка, черепаха, лебедь), то у всех их будет общий метод swim(). В таком случае принято создавать интерфейс, чтобы показать, что у каждого из данных классов есть методы из созданного интерфейса.
Интерфейсы нужны для того, чтобы можно было придавать общее поведение классам, относящимся к разным иерархиям наследования. Бывают плавающие рыбы, плавающие птицы, плавающие млекопитающие и так далее. Не все животные, не все птицы и не все млекопитающие умеют плавать, но утка и кит умеют плавать, при том, что утка не является потомком кита, а кит не является потомком утки.
Значит, мы не можем сделать метод 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();
}
}
Ну и всё-таки читайте учебники, у Шилдта и Экеля всё это очень хорошо описано.
Вам нужно понять, что вам нужно - Duck или Swimmable. Думаю согласитесь, что это разные функциональные сущности. Если в вашей программе будет нужен именно Swimmable, то вы и создаете интерфейс для этих целей.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Такая история, у меня есть проект написаный на C++, который компилируется и работает
В коллекцию через ajax приходят данные в ListКак правильно их обработать и передать в метод? Спасибо! Контроллер:
Есть необходимость добавить АОП для классов из разных бандлов в OSGI (Apache Felix)
Я могу повеcить слушатель на RecyclerView но тогда все предметы будут выполнять одинаковые команды, мне надо чтобы отдельный объект выполнял отдельную...