Эккель Брюс
Шрифт:
//. interfaces/RandomWords java
// Реализация интерфейса для выполнения требований метода
import java nio.*;
import java util.*,
public class RandomWords implements Readable { private static Random rand = new Random(47); private static final char[] capitals =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray; private static final char[] lowers =
"abcdefghijklmnopqrstuvwxyz".toCharArrayO; private static final char[] vowels =
"aeiou" toCharArrayO; private int count,
public RandomWords(int count) { this.count = count: } public int read(CharBuffer cb) { if(count-- == 0)
return -1; // Признак конца входных данных cb.append(capi tals[rand.nextInt(capi ta1s.1 ength) ]); for(int i = 0; i < 4; i++) {
cb.append(vowels[rand.nextInt(vowels.1ength)]); cb append(lowers[rand.nextInt(lowers.length)]),
}
cb.append(" "),
return 10; // Количество присоединенных символов
}
public static void main(String[] args) {
Scanner s = new Scanner(new RandomWords(10)); while(s.hasNextO)
System.out.println(s.nextO);
}
} /* Output:
Yazeruyac
Fowenucor Goeazimom Raeuuacio Nuoadesiw Hageaikux Ruqicibui. Numasetih Kuuuuozog Waqizeyoy */// ~
Интерфейс Readable требует только присутствия метода read. Метод read либо добавляет данные в аргумент CharBuffer (это можно сделать несколькими способами; обращайтесь к документации CharBuffer), либо возвращает -1 при отсутствии входных данных.
Допустим, у нас имеется класс, не реализующий интерфейс Readable, — как заставить его работать с Scanner? Перед вами пример класса, генерирующего вещественные числа:
// interfaces/RandomDoubles java import java util *;
public class RandomDoubles {
private static Random rand = new Random(47), public double next О { return rand nextDouble, } public static void main(String[] args) {
RandomDoubles rd = new RandomDoubles, for(int i = 0, l < 7. i ++)
System out print(rd next О + " "),
}
} /* Output
0 7271157860730044 0 5309454508634242 0 16020656493302599 0 18847866977771732
0 5166020801268457 0 2678662084200585 0 2613610344283964 *///.-
Мы снова можем воспользоваться схемой адаптера, но на этот раз адаптируемый класс создается наследованием и реализацией интерфейса Readable. Псевдомножественное наследование, обеспечиваемое ключевым словом interface, позволяет создать новый класс, который одновременно является и Random-Doubles, и Readable:
//• interfaces/AdaptedRandomDoubles java // Создание адаптера посредством наследования import java nio *. import java util *,
public class AdaptedRandomDoubles extends RandomDoubles implements Readable { private int count;
public AdaptedRandomDoubles(int count) { this count = count,
}
public int read(CharBuffer cb) { if(count-- == 0)
return -1.
String result = Double toString(nextO) + "
cb.append(result); return result.lengthO;
}
public static void main(String[] args) {
Scanner s = new Scanner(new AdaptedRandomDoubles(7)), while(s hasNextDoubleO)
System.out print(s nextDoubleO + " ");
}
} /* Output-
0.7271157860730044 0.5309454508634242 0 16020656493302599 0 18847866977771732 0.5166020801268457 0.2678662084200585 0.2613610344283964 *///•-
Так как интерфейсы можно добавлять подобным образом только к существующим классам, это означает, что любой класс может быть адаптирован для метода, получающего интерфейс. В этом заключается преимущество интерфейсов перед классами.
Поля в интерфейсах
Так как все поля, помещаемые в интерфейсе, автоматически являются статическими (static) и неизменными (final), объявление interface хорошо подходит для создания групп постоянных значений. До выхода Java SE5 только так можно было имитировать перечисляемый тип enum из языков С и С++:
//• interfaces/Months java
// Использование интерфейсов для создания групп констант, package interfaces:
public interface Months { int
JANUARY = 1, FEBRUARY = 2, MARCH = 3, APRIL = 4, MAY « 5. JUNE = 6, JULY = 7, AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10. NOVEMBER = 11, DECEMBER = 12:
} ///-
Отметьте стиль Java — использование только заглавных букв (с разделением слов подчеркиванием) для полей со спецификаторами static и final, которым присваиваются фиксированные значения на месте описания. Поля интерфейса автоматически являются открытыми (public), поэтому нет необходимости явно указывать это.