Философия Java3
Шрифт:
В следующем примере базовый класс Part содержит список объектов-фабрик. Фабрики типов, которые должны создаваться методом createRandom, «регистрируются» в базовом классе включением в список partFactories:
//: typeinfo/RegisteredFactories.java II Регистрация фабрик в базовом классе import typeinfo.factory.*: import java util.*:
class Part {
public String toStringO {
return getClass.getSimpleName;
}
static List<Factory<? extends Part» partFactories = new ArrayList<Factory<? extends Part»0;
static {
// При вызове Collections addAllO выдается предупреждение // "unchecked generic array creation for varargs parameter" partFactories.add(new Fuel Filter FactoryO). partFactories add(new AirFilter FactoryO), partFactories add(new CabinAirFilter.FactoryO), partFactories add(new Oil Filter FactoryO); partFactories add(new FanBelt FactoryO); partFactories.add(new PowerSteeringBelt.Factory), partFactories add(new GeneratorBelt FactoryO),
}
private static Random rand = new Random(47);
public static Part createRandomO {
int n = rand nextInt(partFactories sizeO), return partFactories get(n) createO;
class Filter extends Part {}
class Fuel Filter extends Filter {
//
public static class Factory
implements typeinfo factory.Factory<FuelFilter> {
public Fuel Filter createO { return new Fuel Filter О. }
}
}
class AirFilter extends Filter { public static class Factory implements typeinfo factory Factory<AirFilter> {
public AirFilter createO { return new AirFilterO. }
}
}
class CabinAirFiIter extends Filter { public static class Factory
implements typeinfo factory Factory<CabinAirFilter> { public CabinAi rFi Iter createO {
return new CabinAirFilter;
}
class Oil Filter extends Filter { public static class Factory implements typeinfo factory Factory<OilFilter> {
public Oil Filter createO { return new OilFilterO; }
}
}
class Belt extends Part {}
class FanBelt extends Belt {
public static class Factory
implements typeinfo.factory.Factory<FanBelt> {
public FanBelt createO { return new FanBeltO; }
}
}
class GeneratorBelt extends Belt { public static class Factory
implements typeinfo.factory.Factory<GeneratorBelt> { public GeneratorBelt createO {
return new GeneratorBeltO:
}
class PowerSteeringBelt extends Belt { public static class Factory
implements typei nfо.factory.Factory<PowerSteeri ngBelt> { public PowerSteeringBelt createO {
return new PowerSteeringBeltO;
}
}
}
public class RegisteredFactories {
public static void main(String[] args) { for(int i = 0; i < 10; i++)
System.out.pri ntin(Part.createRandom);
}
} /* Output: GeneratorBelt CabinAirFiIter GeneratorBelt AirFiIter PowerSteeringBelt CabinAirFiIter Fuel Filter PowerSteeringBelt PowerSteeringBelt Fuel Filter *///:-
He все классы иерархии рассчитаны на создание экземпляров; в нашем примере классы Filter и Belt
существуют исключительно в целях классификации. Экземпляры этих классов не создаются — только одного из их субклассов. Если класс должен создаваться посредством createRandom, он содержит внутренний класс Factory.Хотя для включения всех фабрик в список можно воспользоваться вызовом Collections.addAll, компилятор выдает предупреждение, поэтому я вернулся к вызовам add. Метод createRandom случайным образом выбирает объект фабрики из partFactories и вызывает его метод create для получения нового объекта Part.
instanceof и сравнение Class
При получении информации о типе объекта важно различать действие любой формы оператора instanceof (будь это сам оператор instanceof или метод isInstanceO ~~ они дают одинаковые результаты) и прямого сравнения объектов Class. Вот пример, который показывает, в чем их различия:
//. typeinfo/FamilyVsExactType java // Различия между instanceof и class package typeinfo,
import static net mindview util.Print.*, class Base {}
class Derived extends Base {}
public class FamilyVsExactType { static void test(Object x) {
print ("Тестируем x типа " + x.getClassO); printC'x instanceof Base " + (x instanceof Base)), printC'x instanceof Derived "+ (x instanceof Derived)); print("Base.isInstance(x) "+ Base.class.islnstance(x)); print("Derived islnstance(x) " +
Deri ved.class.i slnstance(x)); printC'x getClassO == Base.class " +
(x.getClassO == Base.class)); printC'x.getClassO == Derived.class " +
(x.getClassO == Deri ved. cl ass)). print("x.getClassO.equals(Base.class)) "+
(x getClassO .equals(Base.class))); printC'x getClassO equals (Deri ved. class)) " + (x.getClassO. equals (Deri ved. class)));
}
public static void main(String[] args) { test(new BaseO); test (new DerivedO),
}
} /* Output:
Тестируем x типа class typeinfo.Base x instanceof Base true x instanceof Derived false Base islnstance(x) true Derived islnstance(x) false x getClassO == Base.class true x getClassO == Derived class false x getClassO equals(Base.class)) true x.getClassO equals(Derived.class)) false Тестируем x типа class typeinfo.Derived x instanceof Base true x instanceof Derived true Base.islnstance(x) true Derived.islnstance(x) true x.getClassO == Base.class false x.getClassO == Derived class true x.getClassO equals(Base.class)) false x.getClassO.equals(Derived.class)) true *///:-
Метод test осуществляет проверку типов полученного объекта, используя для этого обе формы оператора instanceof. Затем он получает ссылку на объект Class и использует операцию сравнения ссылок == и метод equals, чтобы проверить объекты Class на эквивалентность. Пример доказывает справедливость утверждения о том, что действие оператора instanceof и метода islnstance одинаково. Совпадают и результаты работы операции сравнения == и метода equals. Но сами тесты приводят к разным заключениям. В соответствии с концепцией типа instanceof дает ответ на вопрос: «Объект принадлежит этому классу или производному от него?» С другой стороны, сравнение объектов Class оператором == не затрагивает наследования — либо тип точно совпадает, либо нет.