Можно ли использовать оператор instanceof для реализации двух параллельных иерархий функций и их аргументов? - PullRequest
5 голосов
/ 26 августа 2011

Является ли плохой практикой использование оператора instanceof в следующем контексте?

public interface IWriter {
    public abstract void write(Dto dto);
}

public abstract class Dto {
    private long id;
    public void setId(long id) {this.id = id;}
    public long getId() {return id;}
}

public class DtoA extends Dto {
   ...
}

public class DtoB extends Dto {
   ...
}

public class MyWriterA implements IWriter {
   @Override
   public void writer(Dto dto) {
     if (!(dto instanceof DtoA))
        return;
     ...
   }
}

public class MyWriterB implements IWriter {
   @Override
   public void writer(Dto dto) {
     if (!(dto instanceof DtoB))
        return;
     ...
   }
}

Существует множество мифов об использовании этого оператора, и я не совсем уверен, что то, что я делаю,не bunk.

У меня есть много различных реализаций писателя, которые я хочу объединить в одном интерфейсе.Проблема не в каждом DTO, применимом к каждому писателю.В моем реальном коде есть глубокая иерархия DTO, которая расширяет DtoA и DtoB, и ветвь иерархии DtoA или DtoB применима для писателя, но только в нескольких случаях.

Следует ли мне избегатьиспользуя абстрактный класс Dto в качестве аргумента для абстрактного write(Dto dto) метода?

РЕДАКТИРОВАТЬ: Пожалуйста, прочитайте комментарии к принятому ответу.

Ответы [ 3 ]

5 голосов
/ 26 августа 2011

Иногда нет смысла использовать instanceof - нет необходимости чувствовать стыд.

Набор текста IWriter может помочь:

public interface IWriter<T extends Dto> {
    public abstract void write(T dto);
}

тогда

public class MyWriterA implements IWriter<DtoA> {
   @Override
   public void writer(DtoA dto) {
     // No need for instanceof, because it can't be anything else
     ...
   }
}

Возможно, комбинация такой печати и достойного ответа Брайана Агнью сработает.

3 голосов
/ 26 августа 2011

Как код вызывает IWriter?Предположительно, вы тоже должны определить тип там?В этом случае вы уже знаете, какой писатель вам нужен.Вы уже отправляете на основе Типа.

Ваши авторы не могут быть заменяемыми.В этом случае вы ничего не получаете, утверждая, что они находятся в иерархии наследования.

3 голосов
/ 26 августа 2011

Рассматривали ли вы двойную диспетчеризацию или шаблон Visitor ?

По существу ваши объекты Writer и DTO будут вызывать правильные методы, например

public void writer(Dto dto) {
   dto.doSomething(writer);
}

и вызываемый метод doSomething() будут зависеть от типа Dto.Ваш Dto объект будет реализовывать версию для MyWriterA/B.

Использование instanceOf не является неизбежным, но часто это дизайнерский запах , указывающий, что что-то не так,или может быть сделано лучше.

...