Несоответствие типов на фабрике объектов

#java #design-patterns

#java #шаблоны проектирования

Вопрос:

Я использую очень простой фабричный класс для создания инициализации некоторых моих объектов:

    public class MyFactory {
      public static Superclass createObject(String type) {
         Superclass myObject = null;
         if (type.equals("type1")) {
            myObject = new Subclass();
            myObject.setParam("val1");
         }
         return myObject;
      }
   }
  

Не так уж и сложно 🙂 Нет общего кода и т. Д., Только так. Тем не менее я получаю ошибку несоответствия типов в Eclipse, если я использую свою фабрику таким образом:

 Subclass myObj = MyFactory.createObject("type1");
  

Ошибка говорит о том, что он не может преобразовать из суперкласса в подкласс, но везде, куда я смотрю (шаблоны проектирования Heads First и т. Д.) Я вижу это так: верните в качестве типа суперкласс созданных подклассов… Итак, почему я получаю эту ошибку :-)? Спасибо!

Комментарии:

1. @Vakimshaar да, абсолютно 🙂

Ответ №1:

Ошибка говорит о том, что он не может преобразовать из суперкласса в подкласс

Это верно. По той же причине вы не можете сохранить a Number в Integer , например (на самом Number деле это может быть a Double !)

Если вы знаете, что Subclass это возвращается ProbeFactory.createProbe("type1") , вы можете использовать его следующим образом:

 Subclass myObj = (Subclass) ProbeFactory.createProbe("type1");
  

По возможности следует избегать приведения вниз. Либо вы разрабатываете его так, чтобы вы могли делать с

 Superclass myObj = ProbeFactory.createProbe("type1");
  

или вы могли бы попытаться создать типобезопасную версию фабрики:

 Subclass myObj = ProbeFactory.createSubProbe("type1");
  

Комментарии:

1. Хорошо, и как это сделать правильно? Как я уже говорил / писал, я нашел это только так, даже в своих книгах… где мое недоразумение?

2. Спасибо за это объяснение, я подумал, что приведение типов — не лучший способ сделать это 🙂 Я подумаю об этом, спасибо!

Ответ №2:

Вы могли бы явно привести возвращаемое значение, к Subclass которому произойдет сбой, как только фабрика вернет другое Subclass из Superclass и выдаст исключение во время выполнения. Поэтому не делайте этого.

Более подходящим способом было бы объявить myObj как type Superclass и иметь интерфейс, содержащий необходимые вам методы. Если вам нужно знать точный возвращаемый подтип, использование заводского шаблона немного бессмысленно.

Комментарии:

1. Я подумаю об этом и, возможно, не буду использовать фабрику или более сложную 🙂

Ответ №3:

Все наоборот. Если вы получаете a SubClass , вы можете присвоить его SuperClass переменной (если мы предполагаем, что подкласс расширяет суперкласс).

Ответ №4:

Поскольку метод возвращает суперкласс, вы не можете напрямую назначить его подклассу.

Вам нужно использовать это или ввести приведение.

 Superclass myObj = ProbeFactory.createProbe("type1");

Subclass myObj = (Subclass) ProbeFactory.createProbe("type1");
  

Комментарии:

1. К сожалению, это приведет к «java.lang. ClassCastException: суперкласс не может быть преобразован в подкласс «.

2. Если вы знаете, что возвращается подкласс, это не так.

3. Но в этом случае приведение больше не требуется.

4. Подкласс myObj = ProbeFactory.createProbe(«type1»); является ошибкой компиляции — не удается преобразовать из суперкласса в подкласс и не будет работать без приведения

Ответ №5:

Обычно вы хотите обрабатывать объекты одной и той же фабрики аналогичным образом, поэтому суперкласс создается для того, чтобы иметь все общее поведение. Если вы действительно хотите использовать их для конкретного класса, тогда, да, вы должны выполнить приведение. Но я чувствую, что это убивает цель абстрактной фабрики.

если вам нужен определенный продукт или группа продуктов при создании подкласса вашей фабрики и получении его с дочерней фабрики