Процедурное программирование достаточно примитивно, его просто освоить. Основным же его минусом является узконаправленность процедурного кода: процедура (в Java — статический метод) выполняет одну задачу. Если требуются какие-то нюансы и отклонения от курса, код процедуры становится громоздким, непонятным, трудноподдерживаемым, т. к. пытается решить задачу «в лоб».
Типы данных, рассмотренные в предыдущей главе, — boolean, int, double и т. п. — называются примитивными. Переменная такого типа хранит одно число из определённого диапазона; название типа говорит только о техническом роде хранимой информации, но не даёт понимания о смысле значения — это может быть количество, координаты и т. п..
Одно значение примитивного типа напоминает атом — очень малую, условно неделимую часть чего-то целого. В жизни мы не рассматриваем окружающие предметы как горстки атомов, мы вводим уровень абстракции и видим, например, чашку кофе, телефон, гитару.
С помощью телефона можно набрать номер и позвонить: на советском стационарном телефоне придётся вращать диск, на Nokia 3310 нужно давить на кнопки, на Nexus 5 нужно нажимать на экранные кнопки. При этом клиенту (пользователю) телефона не обязательно знать его модель, страну производства и дату сборки. Достаточно знать абстракцию — это телефон, можно звонить.
public interface Phone {
void dial(String number);
}
Именно так мы видим телефон извне: с его помощью можно позвонить (dial) по номеру (number), заданному строкой (String). Это всё, что нужно знать для совершения звонка. Это интерфейс телефона, т. е. перечень тех действий, которые с его помощью можно совершать.
Но этого недостаточно для производства телефона.
public final class Nokia3310 implements Phone {
public void dial(String number) {
System.out.println("Передаём номер «" +
number + "» финскому GSM-модулю, сделанному в Венгрии.");
}
}
class Nokia3310 implements Phone означает, что класс Nokia3310 является конкретной реализацией интерфейса (абстрактного понятия) Phone. Это обязывает класс реализовать метод dial(String).
Собираем себе новенькую Nokia 3310 и набираем номер:
public class PhoneTest {
public static void main(String[] args) {
Phone myNewPhone = new Nokia3310();
myNewPhone.dial("+7 (900) 000-00-00");
}
}
Выводится:
Передаём номер «+7 (900) 000-00-00» финскому GSM-модулю, сделанному в Венгрии.
В строке Phone myNewPhone = new Nokia3310(); создаётся новый объект класса Nokia3310 и записывается в локальную переменную myNewPhone типа Phone.
Так как класс Nokia3310 реализует интерфейс Phone (любой экземпляр Nokia3310 является телефоном), его можно хранить в переменной типа Phone.