Эккель Брюс
Шрифт:
RandomList
Рассмотрим еще один пример контейнера: допустим, вам понадобилась особая разновидность списка, которая случайным образом выбирает один из своих элементов при вызове select. Так как класс должен работать для любых объектов, мы воспользуемся параметризацией:
//• generics/RandomList.java import java.util.*;
public class RandomList<T> {
private ArrayList<T> storage'= new ArrayList<T>, private Random rand = new Random(47); public void add(T item) { storage.add(item); } public T selectО {
return storage.get(rand.nextInt(storage.si ze));
}•
public static void main(String[] args) {
RandomList<String> rs = new RandomList<String>; for(String s: ("The quick brown fox jumped over " + "the lazy brown dog").splitC "))
rs. add (s); продолжение & for(int i = 0; i < 11; i++)
System.out.printers.select О + " ");
}
} /* Output:
brown over fox quick quick dog brown The brown lazy brown
Параметризованные интерфейсы
Параметризация работает и с интерфейсами. Например, класс, создающий объекты, называется генератором. В сущности, генератор представляет собой специализированную версию паттерна «метод-фабрика», но при обращении к нему никакие аргументы не передаются, тогда как метод-фабрика обычно получает аргументы. Генератор умеет создавать объекты без дополнительной информации.
Обычно генератор определяет всего один метод — тот, который создает объекты. Назовем его next и включим в стандартный инструментарий:
//• net/mi ndvi ew/uti1/Generator.java
// Параметризованный интерфейс
package net.mi ndvi ew.uti1;
public interface Generator<T> { T nextO; } ///:-
Возвращаемое значение метода next параметризовано по типу Т. Как видите, механизм параметризации работает с интерфейсами почти так же, как с классами.
Чтобы продемонстрировать, как работает реализация Generator, мы воспользуемся иерархией классов, представляющих разные виды кофе:
//: generics/coffee/Coffee.java package generics.coffee;
public class Coffee {
private static long counter = 0; private final long id = counter**; public String toStringO {
return getClassO.getSimpleNameО + " " + id:
}
} Hill-. generics/coffee/Latte.java package generics.coffee; public class Latte extends Coffee {} Hill \ generics/coffee/Mocha.java package generics.coffee; public class Mocha extends Coffee {} Hill : generics/coffee/Cappuccino.java package generics.coffee; public class Cappuccino extends Coffee {} Hill : generics/coffee/Americano.java package generics.coffee;
public class Americano extends Coffee {} /// ~
//. generics/coffee/Breve java
package generics coffee.
public class Breve extends Coffee {} ///:-
Теперь мы можем реализовать интерфейс Generator<Coffee>, который создает случайные типы объектов из иерархии Coffee:
// generics/coffee/CoffeeGenerator.java
// Генератор случайных объектов из иерархии Coffee-
package generics coffee.
import java util *,
import net mindview util.*,
public class CoffeeGenerator
implements Generator<Coffee>, Iterable<Coffee> {
private Class[] types = { Latte class. Mocha.class.
Cappuccino class, Americano.class. Breve class. }; private static Random rand = new Random(47); public CoffeeGeneratorО {} //Для перебора-private int size = 0.
public CoffeeGenerator(int sz) { size = sz;' } public Coffee next О { try {
return (Coffee)
types[rand nextInt(types.length)] newlnstance. // Сообщение об ошибках во время выполнения: } catch(Exception е) {
'throw new RuntimeException(e);
}
}
class Coffeelterator implements Iterator<Coffee> { int count = size;
public boolean hasNextO { return count > 0. } public Coffee next О { count--;
return CoffeeGenerator.this.next.
}
public void removeO { // He реализован
throw new UnsupportedOperationExceptionO;
}
}:
public Iterator<Coffee> iteratorO { return new CoffeeIterator;
}
public static void main(String[] args) {