HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Классы в Java - основы основ, но их описание будет неполным без интерфейсов, с которыми они тесно связаны. Интерфейсы - более простая конструкция, но, как и в случае с классами, полное понимание интерфейсов требует опыта работы с ними. Зачем они нужны? Интерфейсы позволяют задавать требования к классам, то есть какие методы требуются от класса. Предположим, что мы хотим работать в приложении с генератором паролей. Генератор в нашем случае это обычный класс, с методом generate(), возвращающим пароль.</p>
1 <p>Классы в Java - основы основ, но их описание будет неполным без интерфейсов, с которыми они тесно связаны. Интерфейсы - более простая конструкция, но, как и в случае с классами, полное понимание интерфейсов требует опыта работы с ними. Зачем они нужны? Интерфейсы позволяют задавать требования к классам, то есть какие методы требуются от класса. Предположим, что мы хотим работать в приложении с генератором паролей. Генератор в нашем случае это обычный класс, с методом generate(), возвращающим пароль.</p>
2 <p>Теперь с помощью интерфейса опишем требования к классу генератора. Задача интерфейса - определить функционал, который затем будет реализован классами. Поэтому интерфейс содержит только сигнатуру методов без их реализации.</p>
2 <p>Теперь с помощью интерфейса опишем требования к классу генератора. Задача интерфейса - определить функционал, который затем будет реализован классами. Поэтому интерфейс содержит только сигнатуру методов без их реализации.</p>
3 <p>Создадим интерфейс PasswordGenerator и опишем в нем два метода generate(). Один метод будет без параметров, другой - с возможностью настройки длины пароля:</p>
3 <p>Создадим интерфейс PasswordGenerator и опишем в нем два метода generate(). Один метод будет без параметров, другой - с возможностью настройки длины пароля:</p>
4 <p>Теперь интерфейс нужно<strong>реализовать</strong>. Делается это в определении класса:</p>
4 <p>Теперь интерфейс нужно<strong>реализовать</strong>. Делается это в определении класса:</p>
5 <p>Интерфейсы не ограничивают класс в его расширении. Помимо интерфейсных методов, мы можем добавить и любые другие.</p>
5 <p>Интерфейсы не ограничивают класс в его расширении. Помимо интерфейсных методов, мы можем добавить и любые другие.</p>
6 <p>Но все таки одно ограничение есть. Если класс применяет интерфейс, то он должен реализовывать все методы, указанные в интерфейсе, причем именно так, как они описаны.</p>
6 <p>Но все таки одно ограничение есть. Если класс применяет интерфейс, то он должен реализовывать все методы, указанные в интерфейсе, причем именно так, как они описаны.</p>
7 <p>В чем же суть интерфейсов? Если коротко: полиморфизм, а если точнее - полиморфизм подтипов (<a>subtyping</a>). Прямо сейчас он нам не очень нужен, но для общего развития попробуем ухватить его идею.</p>
7 <p>В чем же суть интерфейсов? Если коротко: полиморфизм, а если точнее - полиморфизм подтипов (<a>subtyping</a>). Прямо сейчас он нам не очень нужен, но для общего развития попробуем ухватить его идею.</p>
8 <p><em>Осторожно, дальнейший текст может напугать. Если он кажется вам сложным, просто пропустите, все это мы будем повторять еще не раз.</em></p>
8 <p><em>Осторожно, дальнейший текст может напугать. Если он кажется вам сложным, просто пропустите, все это мы будем повторять еще не раз.</em></p>
9 <p>Код, который будет использовать passwordGenerator может выглядеть так:</p>
9 <p>Код, который будет использовать passwordGenerator может выглядеть так:</p>
10 <p>Неплохой код, но представьте, что класс может меняться без изменения кода, просто в зависимости от того, какие опции выбирает пользователь при генерации пароля. Вполне реальная ситуация. Самый простой способ реализовать такую схему - вставить условие на параметр, который вводит пользователь. В одном случае берем один класс, в другом другой.</p>
10 <p>Неплохой код, но представьте, что класс может меняться без изменения кода, просто в зависимости от того, какие опции выбирает пользователь при генерации пароля. Вполне реальная ситуация. Самый простой способ реализовать такую схему - вставить условие на параметр, который вводит пользователь. В одном случае берем один класс, в другом другой.</p>
11 <p>Такой код уже может стать проблемой, если генераторы будут постоянно добавляться. Ситуация ухудшится, когда эта конструкция начнет расползаться по разным частям проекта. Интерфейсы изящно решают такие ситуации.</p>
11 <p>Такой код уже может стать проблемой, если генераторы будут постоянно добавляться. Ситуация ухудшится, когда эта конструкция начнет расползаться по разным частям проекта. Интерфейсы изящно решают такие ситуации.</p>
12 <p>Сделаем так, чтобы класс SuperPasswordGenerator() тоже реализовывал интерфейс PasswordGenerator:</p>
12 <p>Сделаем так, чтобы класс SuperPasswordGenerator() тоже реализовывал интерфейс PasswordGenerator:</p>
13 <p>Код, который будет использовать PasswordGenerator, меняется на такой:</p>
13 <p>Код, который будет использовать PasswordGenerator, меняется на такой:</p>
14 <p>Интерфейсы в Java - это настоящие типы данных, поэтому их можно указывать в определениях методов.</p>
14 <p>Интерфейсы в Java - это настоящие типы данных, поэтому их можно указывать в определениях методов.</p>
15 <p>В коде выше видно, что мы требуем передавать в метод create тип PasswordGenerator. Таким типом будет любой объект, класс которого реализует интерфейс PasswordGenerator. Теперь мы можем передать в метод create() любой генератор паролей, который реализует интерфейс PasswordGenerator. В получившемся коде генератор создается не там, где используется. Он создается где-то раньше, а уже в код приходит нужная реализация.</p>
15 <p>В коде выше видно, что мы требуем передавать в метод create тип PasswordGenerator. Таким типом будет любой объект, класс которого реализует интерфейс PasswordGenerator. Теперь мы можем передать в метод create() любой генератор паролей, который реализует интерфейс PasswordGenerator. В получившемся коде генератор создается не там, где используется. Он создается где-то раньше, а уже в код приходит нужная реализация.</p>
16 <p>Таким образом мы можем получить разное поведение, не меняя сам код, который использует PasswordGenerator.</p>
16 <p>Таким образом мы можем получить разное поведение, не меняя сам код, который использует PasswordGenerator.</p>
17 <p>Все это уже станет актуальным, как только мы дойдем до Java-коллекций.</p>
17 <p>Все это уже станет актуальным, как только мы дойдем до Java-коллекций.</p>
18 <h2>Соглашения и правила</h2>
18 <h2>Соглашения и правила</h2>
19 <p>К интерфейсам предъявляются такие же требования как и к классам</p>
19 <p>К интерфейсам предъявляются такие же требования как и к классам</p>
20 <ol><li>Один файл - один интерфейс. Имя файла и интерфейса совпадают.</li>
20 <ol><li>Один файл - один интерфейс. Имя файла и интерфейса совпадают.</li>
21 <li>Интерфейсы начинаются с заглавной буквы.</li>
21 <li>Интерфейсы начинаются с заглавной буквы.</li>
22 </ol>
22 </ol>