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

Открыта

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

Интерфейсы — это больше чем интерфейсы — это поведение - 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
{
...
}
— класс «скейтборд». Обладает способностью передвигаться и управляться человеком.

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

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

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

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

Код на 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();
   }
  }
 }
}
— как дать им команду – построить стену?

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

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

3
Задача
Java Core,  2 уровень,  8 лекция
Недоступна
Набираем код Ӏ Java Core: 2 уровень, 8 лекция
Java Core: 2 уровень, 8 лекция. Иногда думать не надо, строчить надо! Как ни парадоксально звучит, порой пальцы «запоминают» лучше, чем сознание. Вот почему во время обучения в секретном центре JavaRush вы иногда встречаете задания на набор кода. Набирая код, вы привыкаете к синтаксису и зарабатываете немного материи. А ещё — боретесь с ленью.
Комментарии (185)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
Николай Т.13 уровень, Рязань
воскресенье, 20:25
Но как же так, сначала сказали что робот-поливалка умеет строить стены, а потом оказывается что нет.
Maria16 уровень, Utrecht
25 июля, 17:40
ох уж этот перевод 🤦‍♀️ this is папа, this is мама, worker вместо employee, теперь это
Lizaveta:)15 уровень, Киев
22 июня, 07:03
Буду очень рада, если кто-то ответит на такой вот вопрос: Можно ли одновременно унаследовать класс от другого класса и от интерфейса?
Иван16 уровень, Москва
22 июня, 20:04
Я не эксперт, но вроде бы да. Интерфейс может иметь несколько интерфейсов родителей. Класс может иметь несколько интерфейсов родителей и только один класс родитель.
Lizaveta:)15 уровень, Киев
22 июня, 21:12
Спасибо)
Dmytro Yantsybaiev13 уровень, Киев
24 июня, 19:47
Да, можно. Это будет выглядеть примерно так:
public class Horse extends Animal implements Moveable, Driveable {
}
Wan-Derer14 уровень, Москва
воскресенье, 03:28
Когда возникает какой-то вопрос, лучше набрать кусок кода в ИДЕ - она сразу скажет что можно, что нельзя :)
Lizaveta:)15 уровень, Киев
понедельник, 05:31
В этом случае да, но вот буквально позавчера столкнулась с тем, что некоторые вещи идея все таки пропускает :) Хотя последнее обновление просто уже пишет код за тебя)
Plunder17 уровень, Санкт-Петербург
15 июня, 15:38
Короче, класс — это существительное. А интерфейс — инфинитив.
Dmitriy Zinevich12 уровень, Санкт-Петербург
23 июня, 09:18
А метод - глагол?
Kirill Gorbunov17 уровень, Москва
10 июля, 18:06
А модификаторы доступа - прилагательные?
Yulia26 уровень
19 мая, 17:04
В примере с роботами ошибка - такой код не скомпилируется, потому что забыто слово public. У интерфейсов абстрактные методы по умолчанию public, а если мы переопределяем метод в классе, который имплементирует данный интерфейс, то нельзя писать без public. Должно быть так: static class РабочийРобот implements WallBuilder { public void buildWall() { … } } А не так: static class РабочийРобот implements WallBuilder { void buildWall() // здесь default { … } }
Ivan Matveenko25 уровень, Омск
12 июня, 07:38
ты первая кто заметил ошибку)👍👍
Nastya26 уровень, Москва
18 мая, 07:17
Объясните эту строку, пожалуйста
WallBuilder builder = (WallBuilder) robot;
   builder.buildWall();
Alexandr Mihailovich20 уровень, Kursk
18 мая, 15:14
мне тоже непонятно, зачем привели в типу WallBuilder? мы же и так проверили ифом, что объект принадлежит интерфейсу, можно же просто robot.buildWall()
Life DIY15 уровень, Екатеринбург
19 мая, 12:46
потому что мы перебираем объекты из robots: for (Object robot : robots) {} проверяем есть ли у объекта нужный implement и приводим robot (который сейчас Object) к нужному нам WallBuilder'у
Alexandr Mihailovich20 уровень, Kursk
20 мая, 08:27
так все объекты унаследованы от Object... но мы же проверили, что робот и так экземпляр WallBuilder
if (robot instanceof WallBuilder)
так, что прихожу к выводу, что строка
WallBuilder builder = (WallBuilder) robot;
для лучшей читаемости кода и, чтобы не менять состояние исходного робота
John Rain20 уровень
21 мая, 14:35
они то унаследованы от Object, но объект имеет в распоряжении только те методы, которые определены в классе переменной, ссылающейся на этот объект. поэтому у robot нет доступа к методу buildWall(), есть только методы Object => надо привести robot к нужному типу
Alexandr Mihailovich20 уровень, Kursk
21 мая, 15:09
да, так и есть. проверил сомнение на практике, вопросов нет по данному моменту
Александр Евтеев17 уровень, Москва
28 апреля, 03:04
Только в примере Робот-поливалка не умеет строить стены ))
Вячеслав16 уровень
3 мая, 11:37
но его элегантно отсекают в коде в цикле:
if (robot instanceof WallBuilder)
zatolokinboris22 уровень, Москва
24 апреля, 10:09
Хорошее видео на тему интерфейсов: https://www.youtube.com/watch?v=uCgF5-yCbGA&t=2s
Anton13 уровень
16 апреля, 13:38
Я тут что подумал, насчет русских имен классов, методов, переменных. Как-то делали ученые анализ длины команд во время второй Мировой войны. У русских получалось что-то около 3 с небольшим символов на команду, в среднем. Ибо одно матное слово может очень сильно сократить текст, а смысла передать очень много :-D Может и имеет смысл в русских именах переменных, классов, методов :-D
Андрей18 уровень, Пермь
13 апреля, 16:00
Очень посмеялся с поливалки 😂