Интерфейсы — это больше чем интерфейсы — это поведение

Открыта

— Привет, Амиго! А вот и снова я. Хочу рассказать тебе еще об одном взгляде на интерфейсы. Понимаешь, класс – это, чаще всего модель какого-то конкретного объекта. Интерфейс же больше соответствует не объектам, а их способностям или ролям.

Интерфейсы — это больше чем интерфейсы — это поведение - 1

Например, такие вещи, как машина, велосипед, мотоцикл и колесо лучше всего представить в виде классов и объектов. А такие их способности как «могу ездить», «могу перевозить людей», «могу стоять» — лучше представить в виде интерфейсов. Смотри пример:

Код на Java Описание
interface Moveable
{
void move(String newAddress);
}
— соответствует способности передвигаться.
interface Driveable
{
void drive(Driver driver);
}
— соответствует способности управляться водителем.
interface Transport
{
void addStaff(Object staff);
Object removeStaff();
}
— соответствует способности перевозить грузы.
class Wheel implements Moveable
{
...
}
— класс «колесо». Обладает способностью передвигаться.
class Car implements Moveable, Drivable, Transport
{
...
}
— класс «машина». Обладает способностью передвигаться, управляться человеком и перевозить грузы.
class Skateboard implements Moveable, Driveable
{
...
}
— класс «скейтборд». Обладает способностью передвигаться и управляться человеком.
3
Задача
Java Core,  2 уровень,  8 лекция
Недоступна
Набираем код Ӏ Java Core: 2 уровень, 8 лекция
Java Core: 2 уровень, 8 лекция. Иногда думать не надо, строчить надо! Как ни парадоксально звучит, порой пальцы «запоминают» лучше, чем сознание. Вот почему во время обучения в секретном центре JavaRush вы иногда встречаете задания на набор кода. Набирая код, вы привыкаете к синтаксису и зарабатываете немного материи. А ещё — боретесь с ленью.

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

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

Представь, что ты – робот-строитель и у тебя в подчинении есть десятки роботов, каждый из которых может иметь несколько профессий. Тебе нужно срочно достроить стену. Ты просто берешь всех роботов, у которых есть способность «строитель» и говоришь им строить стену. Тебе все равно, что это за роботы. Хоть робот-поливалка. Если он умеет строить – пусть идет строить.

Вот как это выглядело бы в коде:

Код на Java Описание
static interface WallBuilder
{
void buildWall();
}
— способность «строитель стен». Понимает команду «(по)строить стену» — имеет соответствующий метод.
static class РабочийРобот implements WallBuilder
{
void buildWall()
 {}
}
static class РоботСторож implements WallBuilder
{
void buildWall()
 {}
}
static class Поливалка
{}
— роботы у которых есть эта профессия/особенность.

— для удобства я сделал классам имена на русском. Такое допускается в java, но крайне нежелательно.

— поливалка не обладает способностью строить стены (не реализует интерфейс WallBuilder).

public static void main(String[] args)
{
 //добавляем всех роботов в список
 ArrayList robots = new ArrayList();
 robots.add(new РабочийРобот());
 robots.add(new РоботСторож());
 robots.add(new Поливалка());

 //строить стену, если есть такая способность
 for (Object robot: robots)
 {
  if (robot instanceof WallBuilder)
  {
   WallBuilder builder = (WallBuilder) robot;
   builder.buildWall();
   }
  }
 }
}
— как дать им команду – построить стену?

— Чертовски интересно. Даже и не думал, что интерфейсы – такая интересная тема.

— А то! В совокупности с полиморфизмом – это вообще бомба.

Комментарии (204)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
Mr Notorious 12 уровень, Санкт-Петербург
около 8 часов назад
Интересно, а почему в последнем примере не написать просто for (Object robot: robots) { if (robot instanceof WallBuilder) { robot.buildWall(); } } Зачем явно приводить объекты к типу WallBuilder? Ведь сами объекты по идее уже должны иметь метод buildWall().
🦔 Виктор админ Java Android канала в telegram @LetsCodeItExpert
24 декабря 2020, 16:29
Now we're talking! Совсем другое дело, общий принцип и концепция понятна, наглядные примеры, спасибо. Теперь можно приступать к задачам и отрабатывать ключевое слово interface ; ) Дополнительные материалы про интерфейсы: Видео-урок от Алишева про интерфейсы. Разница между абстрактными классами и интерфейсами. Интерфейсы для тех кому "очень интересно, но ничего не понятно". Для чего в Java нужны интерфейсы. Всё получится! -- tlgrm: @LetsCodeIt | @SefoNotasi
Lilly 18 уровень, Москва
18 декабря 2020, 21:44
Я тут попробовала объяснить назначение интерфейсов простыми словами. Может, кому-то поможет. Было бы здорово =) Интерфейсы для тех кому "очень интересно, но ничего не понятно"
Дима Сидельников 15 уровень, Варшава
15 декабря 2020, 16:55
Для меня лучшее объяснение интерфейсов такое. У вас есть класс абстрактный класс Работники (super класс), в нем есть методы Работать, Идти на обед, Идти домой. Все классы наследники (sub классы) Пожарный, врач, водитель, слесарь унаследуют эти методы. Также каждый класс имеет свои собственный методы, врач говорит с детьми, водитель едет, а пожарный несет шланг. Но допустим вы хотите, чтобы ТОЛЬКО НЕКОТОРЫЕ классы "умели плавать" или "оказывать первую помощь", или и то и другое. Конечно можно создать этот метод только в нужных классах, но ТОГДА наследники уже этих классов тоже получат "ненужные им навыки". Вот тут вступает в игру Интерфейс. вы создаете например интерфейс с умением только "плавать" и умениями "плавать и оказывать первую помощь" или просто "оказывать помощь". Тогда уже нужные интерфейсы только с нужными классу "навыками" и имплементируете в классы. Не знаю как вам, но мне такое объяснение лучше всего дало понять, что к чему. Возможно, в чем-то ошибся, тогда поправьте)
Vsevolod 13 уровень, Москва
12 декабря 2020, 04:00
второй раз сталкиваемся с
ArrayList robots = new ArrayList();
что это вообще такое и почему тут не указан тип?
Дима Сидельников 15 уровень, Варшава
15 декабря 2020, 16:06
До конца с этим не разобрался, но постараюсь ответить на основе того, что знаю.
ArrayList robots = new ArrayList();
Такой способ записи называется RAW type. Дословный перевод будет вполне точным — «сырой тип» или «грязный тип».
List myList1
или как в данном случае
ArrayList robots
Это Raw type. Противоположностью raw type является generic type - класс-дженерик (также известный как parameterized type), созданный правильно, с указанием типа. Например,
List<String> myList1
или
ArrayList<String> robots
Мог возникнуть вопрос: а почему в языке вообще позволено использовать raw types? Причина проста. Создатели Java оставили в языке поддержку raw types чтобы не создавать проблем с совместимостью. К моменту выхода Java 5.0 (в этой версии впервые появились дженерики) было написано уже очень много кода с использованием raw types. Поэтому такая возможность сохраняется и сейчас. Скорее всего эта тема будет рассматриваться дальше более подробно, но пока вот что имеем)
Jh-007 31 уровень, Kansk-City
27 декабря 2020, 03:44
Еще в таком ArrayList хранятся Object o. А так как все классы наследуют от Object, то в такой лист можно поместить любой тип, кроме примитивных. т.е. и Integer и String, причем одновременно.
Сергей 17 уровень, Москва
6 декабря 2020, 15:08
Считаю, что "Набираем код" могла бы предоставлять побольше строк кода, затрагивающего весь новый материал уровня. Ведь написание десятков различных вариантов новой информации запомнится лучше, чем какая-то одна строка кода. 😔
Николай 15 уровень, Гомель
6 декабря 2020, 12:52
зачем приведение типа?
WallBuilder builder = (WallBuilder) robot;
   builder.buildWall()
если робот реализует интерфейс, то реализует и методы этого интерфейса. должно работать и без приведения к WallBuilder.
robot.buildWall()
Nikolay Kapuza 13 уровень, Ставрополь
6 ноября 2020, 18:13
Не понимаю, как интерфейс может быть Static?
dmitrii_94 15 уровень, Кишинёв
30 октября 2020, 11:26
Этот парниша вам точьно поможет https://www.youtube.com/watch?v=uCgF5-yCbGA (интерфейсы)
Е К 20 уровень, Краснодар
12 октября 2020, 16:12
Не понял я чего-то из последнего примера. WallBuilder builder = (WallBuilder) robot; В этой строчке мы создаём ссылку типа WallBuilder и приводим объект robot к типу WallBuilder, присваивая этой ссылке. То есть неявно создаём объект типа WallBuilder? Но WallBuilder - это же интерфейс, и объектов с таким типом никак не создать. не догнал какбып) Подскажите, люди добрые, кто догнал?
Dara Software Developer
13 октября 2020, 09:24
В примере мы присваиваем, а не создаем явно новый объект типа WallBuilder Это как в случае с интерфейсом List. Такой вариант сработает: List<String> list = new ArrayList<String>(); При этом, если мы явно попытаемся создать объект интерфейса List через new, то ничего не выйдет, потому что List является абстрактным и его объекты нельзя создать: List<String> list = new List<String>();
Е К 20 уровень, Краснодар
13 октября 2020, 15:09
Теперь догнал! Спасибо за пояснения! И точно же - не создаём новый, а даём понять компилятору, что теперь ссылка builder хранит объект robot с интерфейсом WallBiulder, и для неё возможен вызов функции *.buildWall() Загнал этот код в Idea и попробовал прямое обращение robot.buildWall(); - вне проверки instanceof - оказывается компилятор не понимает чего от него хотят. Ругается на название функции buildwall(), хотя ведь у объекта по этой ссылке есть применение интерфейса этой функции и её описание... А мог бы, на мой взгляд. Ведь зачем городить огород, если можно за шторами сделать проверку для объекта robot из списка - ест ли у него поддержка интерфейса вызываемой функции или нет. Если нет, то тогда исключение. Это так, фантазии) Потому Java и один из самых надёжных, наверное, языков. Так как не допускает подобных(и других интересных) фокусов.