Эккель Брюс
Шрифт:
IH typeinfo/pets/EgyptianMau java package typeinfo.pets;
public class EgyptianMau extends Cat { продолжение &
public EgyptianMau(String name) { super(name); } public EgyptianMau { superO; } } ///–
// typeinfo/pets/Manx java package typeinfo pets,
public class Manx extends Cat {
public Manx(String name) { super(name); } public ManxO { superO; }
} 111
II typeinfo/pets/Cymric java package typeinfo pets,
public class Cymric extends Manx {
public Cymric(String name) { super(name). } public CymricO { superO; } } III -
II. typeinfo/pets/Rodent java package typeinfo pets,
public class Rodent extends Pet {
public Rodent(String name) { super(name), } public RodentO { superO; } } III -
II' typeinfo/pets/Rat java package typeinfo pets,
public class Rat extends Rodent {
public Rat(String name) { super(name); } public RatO { superO; } } Hill' typeinfo/pets/Mouse java package typeinfo pets;
public class Mouse extends Rodent {
public Mouse(String name) { super(name); } public MouseO { superO, } } ///:-
II typeinfo/pets/Hamster java package typeinfo pets.
public class Hamster extends Rodent {
public Hamster(String name) { super(name); } public HamsterO { superO; } } ///:-
Затем нам понадобятся средства для создания случайных типов Pet, а для удобства — массивов и списков (List) с элементами Pet. Чтобы этот инструментарий мог «пережить» несколько разных реализаций, мы определим его в виде абстрактного класса:
// typeinfo/pets/PetCreator java // Создание случайных последовательностей Pet package typeinfo pets, import java util *,
public abstract class PetCreator {
private Random rand = new Random(47), // Список создаваемых типов, производных от Pet public abstract List<Class<? extends Pet» typesO. public Pet randomPetO { // Создание одного случайного объекта Pet int n = rand next Int (types О sizeO), try {
return typesO get(n) newInstanceO. } catchdnstantiationException e) {
throw new RuntimeException(e), } catchdllegalAccessException e) {
throw new RuntimeException(e).
}
}
public Pet[] createArray(int size) { Pet[] result = new Pet[size], for(int i = 0. i < size, i++)
result[i] = randomPetO. return result;
}
public ArrayList<Pet> arrayList(int size) {
ArrayList<Pet> result = new ArrayList<Pet>, Collections addAll(result, createArray(size)), return result,
}
} /// ~
Абстрактный метод getTypes поручает производному классу получение списка объектов Class. В качестве типа класса указан «любой производный от Pet», поэтому newlnstance создает Pet без необходимости преобразования типа. Метод randomPet осуществляет случайную выборку из List и использует полученные объекты Class для создания нового экземпляра данного класса вызовом Class. newlnstance. Метод createArray использует randomPet для заполнения массива, a arrayList, в свою очередь, использует createArray.
При вызове newlnstance возможны два вида исключений, обрабатываемые в секциях catch за блоком try. Имена исключений достаточно хорошо объясняют суть проблемы (IllegalAccessException — нарушение механизма безопасности Java, в данном случае если конструктор по умолчанию объявлен private).
Определяя субкласс PetCreator, достаточно предоставить список типов Pet, которые должны создаваться с использованием randomPet и других методов. Метод getTypes возвращает ссылку на статический объект List. Реализация с использованием forName выглядит так:
//• typei nfo/pets/ForNameCreator.java package typeinfo pets; import java util *;
public class ForNameCreator extends PetCreator {
private static List<Class<? extends Pet» types =
new ArrayList<Class<? extends Pet». Л Л
продолжение &
II Типы, создаваемые случайным образом, private static StringE] typeNames = { "typeinfo pets.Mutt", "typeinfo pets Pug", "typeinfo pets EgyptianMau", "typeinfo pets.Manx", "typeinfo.pets.Cymric", "typeinfo.pets.Rat", "typeinfo.pets.Mouse", "typeinfo pets.Hamster"
}:
@SuppressWarni ngs("unchecked") private static void loaderO { try {
for(String name : typeNames) types.add(
(Class<? extends Pet>)Class forName(name)). } catch(ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
static { loaderO; }
public List<Class<? extends Pet» types О {return types,} } ///:-
Метод loader создает список List объектов Class с использованием метода Class.forName. При этом может произойти исключение ClassNotFoundException, что вполне понятно — ведь ему передается строка, содержимое которой невозможно проверить на стадии компиляции. При ссылке на эти классы необходимо указывать имя пакета, которому они принадлежат (typeinfo).