Вообще же наличие и классов, и интерфейсов дает разработчику богатые возможности проектирования. В нашем примере вы можете включить в хор любой класс, просто реализовав в нем интерфейс Voice.
Наконец, можно использовать интерфейсы просто для определения констант, как показано в листинге 3.4.
Листинг 3.4. Система управления светофором
int ERROR = -1;
}
class Timer implements Lights{ private int delay; private static int light = RED;
Timer(int sec){delay = 1000 * sec;} public int shift(){
int count = (light++) % 3; try{
switch (count){
case RED: Thread.sleep(delay); break;
case YELLOW: Thread.sleep(delay/3); break; case GREEN: Thread.sleep(delay/2); break;
}
}catch(Exception e){return ERROR;} return count;
}
} class TrafficRegulator{
private static Timer t = new Timer(1);
public static void main(String[] args){
System.out.println("Stop!"); break;
System.out.println("Wait!"); break; System.out.println("Walk!"); break; System.err.println("Time Error"); break; System.err.println("Unknown light."); return;
for(int k = 0; k < 10; k++) switch(t.shift()){ case Lights.RED: case Lights.YELLOW: case Lights.GREEN: case Lights.ERROR: default:
}
}
Здесь, в интерфейсе Lights, определены константы, общие для всего проекта.
Класс Timer реализует этот интерфейс и использует константы напрямую как свои собственные. Метод shift() этого класса подает сигналы переключения светофору с разной задержкой в зависимости от цвета. Задержку осуществляет метод sleep () класса Thread из стандартной библиотеки, которому передается время задержки в миллисекундах. Этот метод нуждается в обработке исключений try{}catch(){}, о которой мы будем говорить в главе 21.
Класс TrafficRegulator не реализует интерфейс Lights и пользуется полными именами Lights.RED и т. д. Это возможно потому, что константы RED, YELLOW и GREEN по умолчанию являются статическими.
Перечисления
Просматривая листинг 3.4, вы, наверное, заметили, что создавать интерфейс только для записи констант не совсем удобно. Начиная с версии Java SE 5 для этой цели в язык введены перечисления (enumerations). Создавая перечисление, мы сразу же указываем константы, входящие в него. Вместо интерфейса Lights, описанного в листинге 3.4, можно воспользоваться перечислением, сделав такую запись:
enum Lights{ RED, YELLOW, GREEN, ERROR }
Как видите, запись сильно упростилась. Мы записываем только константы, не указывая их характеристики. Каков же, в таком случае, их тип? У них тип перечисления Lights.
Перечисления в языке Java образуют самостоятельные типы, что указывается словом enum в описании перечисления, но все они неявно наследуют абстрактный класс java.lang.Enum. Это наследование не надо указывать словом extends, как мы обычно делаем, определяя классы. Оно введено только для того, чтобы включить перечисления в иерархию классов Java API. Тем не менее мы можем воспользоваться методами класса Enum для получения некоторых характеристик перечисления, как показано в листинге 3.5.
Листинг 3.5. Общие свойства перечислений
enum Lights { RED, YELLOW, GREEN, ERROR }
public class EnumMethods{
public static void main(String[] args){ for (Lights light: Lights.values()){
System.out.println("Тип: " + light.getDeclaringClass());
System.out.println("4HcnoBoe значение: " + light.ordinal());
}
}
}
Обратите внимание, во-первых, на то, как задается цикл для перебора всех значений перечисления Lights. В заголовке цикла определяется переменная light типа перечисления Lights. Метод values (), имеющийся в каждом перечислении, дает ссылку на его значения. Эти значения получает последовательно, одно за другим, переменная light.
Во-вторых, посмотрите, как можно узнать тип значений перечисления. Его возвращает метод getDeclaringClass ( ) класса Enum. В случае листинга 3.5 мы получим тип Lights.
В-третьих, у каждой константы, входящей в перечисление, есть свой порядковый номер 0, 1, 2 и т. д. Его можно узнать методом ordinal ( ) класса Enum.
Перечисление — это не только собрание констант. Это полноценный класс, в котором можно определить поля, методы и конструкторы. Мы уже видели, что в каждом перечислении есть методы, унаследованные от класса Enum, например метод values (), возвращающий массив значений перечисления.
Расширим определение перечисления Lights. Для использования его в классе TrafficRegulator нам надо сделать так, чтобы числовое значение константы error было равно -1 и чтобы методом shift() можно было бы получить следующую константу. Этого можно добиться следующим определением:
enum Lights{
RED(0), YELLOW (1), GREEN(2), ERROR(-1); private int value;private int currentValue = 0;
Lights(int value){ this.value = value;} public int getValue(){ return value; }
public Lights nextLight(){
currentValue = (currentValue + 1) % 3; return Lights.values()[currentValue];
}
}
Как видите, теперь константы создаются конструктором, определяющим для каждой константы поле value. А сейчас можно применить полученное перечисление Lights для регулирования дорожного движения. Это сделано в листинге 3.6.
Листинг 3.6. Система управления светофором с перечислением
enum Lights{
Читать дальше
Конец ознакомительного отрывка
Купить книгу