Как я могу сравнивать объекты, используя instanceof, но типы интерфейса (не передавая точное имя класса.)

public interface Component{}

public class AppManager {


  public void doWork(){
    SomeComponent comp = new SomeComponent ();
    AddComponentToList(comp);

  }

  public void AddComponentToList(Component compo){
     componentList.add(compo);
  }

  /* Give me the component I want. */
  public Component getComponent(Component comp){
    for (Component component : getComponentList()) {

        if (component instanceof comp) {
          return component;  
        }

    }


  }

   private ArrayList<Component> componentList  = new ArrayList<Component>();

}

public class SomeComponent implements component {

  public void MyMethod() {

     appManager.getComponent(SomeComponent );
  }


  public void setAppMnger(AppManager appm){
     this.appManager = appm;
  }

  private AppManager appManager ;
}

В приведенном выше коде AppMnger имеет список компонентов. Компоненты взаимодействуют друг с другом. Поэтому, если один компонент хочет узнать экземпляр другого компонента, он вызывает метод AppMnger getComponent(comp). Но я получаю сообщение об ошибке, когда использую оператор instanceof. Я не хочу, чтобы каждый компонент хотел сравнить список, но я хочу делегировать эту задачу AppMnger, потому что он тот, кто знает о созданных им компонентах. Эми подумала?


person user2771655    schedule 19.09.2013    source источник
comment
Побочный комментарий. Я настоятельно рекомендую вам избегать удаления гласных ради краткости. AppManager или даже ApplicationManager — лучшие имена, чем AppMnger.   -  person Jon Skeet    schedule 19.09.2013
comment
stackoverflow.com/ вопросы/10165887/   -  person kovrik    schedule 19.09.2013
comment
Есть несколько вопросов, которые вы могли бы попытаться задать об отношениях между component и comp, например, имеют ли они один и тот же класс?, или какой-либо интерфейс, который они оба реализуют?, или они оба реализуют какой-либо из этого набора интерфейсов? . На все эти вопросы можно было бы ответить, учитывая две ссылки. Можете быть более конкретными?   -  person Patricia Shanahan    schedule 19.09.2013
comment
Я хочу проверить и найти из componentList точный конкретный экземпляр класса, который мне нужен. Я передаю appMnger.getComponent(SomeComponent); и я хочу найти экземпляр SomeComponent из списка.   -  person user2771655    schedule 19.09.2013


Ответы (3)


Я думаю, вам следует изменить дизайн getComponent, чтобы использовать Class<? extends Component>, а не Component. Затем вы можете использовать isInstance:

public Component getComponent(Class<? extends Component> componentClass) {
    for (Component component : getComponentList()) {
        if (componentClass.isInstance(component)) {
           return component;  
        }
    }
    return null; // Or throw an exception, potentially.
}

И SomeComponent будет использовать:

appManager.getComponent(SomeComponent.class);

Если вы действительно хотите использовать экземпляр, вы можете перегрузить метод следующим образом:

public Component getComponent(Component existingComponent) {
    return getComponent(existingComponent.getClass());
}

РЕДАКТИРОВАТЬ: Если вы на самом деле хотите проверить только класс exact, вам не нужно поведение, подобное instanceof - вам просто нужно:

public Component getComponent(Class<? extends Component> componentClass) {
    for (Component component : getComponentList()) {
        if (componentClass == component.getClass()) {
           return component;  
        }
    }
    return null; // Or throw an exception, potentially.
}

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

person Jon Skeet    schedule 19.09.2013
comment
привет Джон, я пытаюсь использовать первый вариант, и это дало мне ошибку о том, что не удается найти оператор возврата. - person user2771655; 19.09.2013
comment
@user2771655: user2771655: Исправлено - это была проблема в вашем исходном псевдокоде, которую я не заметил. - person Jon Skeet; 19.09.2013
comment
OK. Это создало мне еще одну проблему. Почему он не находит оператор return внутри блока if? - person user2771655; 19.09.2013
comment
@user2771655: user2771655: Да, но если метод имеет непустой тип возвращаемого значения, вы не можете добраться до конца метода, не возвращая что-либо. Рассмотрим случай, когда вообще нет компонентов или, в более общем случае, если нет компонентов, соответствующих указанному типу — что вы хотите, чтобы произошло тогда? - person Jon Skeet; 19.09.2013
comment
Я получаю эту ошибку при передаче SomeComponent.class в getComponent(). Метод getComponent(Class‹? extends Component›) в типе ApplicationManager неприменим для аргументов - person user2771655; 19.09.2013
comment
Джон, пожалуйста, проигнорируйте комментарий выше. Я сделал ошибку. - person user2771655; 19.09.2013
comment
Как я могу использовать это с предыдущей версией Java 1.5. - person user2771655; 15.10.2013
comment
Ну, вы вообще не можете использовать дженерики до Java 1.5 или расширенного цикла for. Тем не менее, вы все равно можете вызывать iterator() и каждый раз просто приводить результат next(). - person Jon Skeet; 15.10.2013

Если вы хотите, чтобы класс точно соответствовал (List != ArrayList), используйте это:

if (comp.getClass().equals(component.getClass())) ...

Если вы хотите, чтобы он работал точно так же, как instanceof (List => ArrayList), вы можете попробовать это:

if (comp.getClass().isInstance(component)) ...
person bezmax    schedule 19.09.2013
comment
Основываясь на поясняющем комментарии, я хочу проверить и найти из componentList точный конкретный экземпляр класса, который мне нужен. Я передаю appMnger.getComponent(SomeComponent); и я хочу найти экземпляр SomeComponent из списка. Я думаю, что первый вариант правильный ответ. - person Patricia Shanahan; 19.09.2013
comment
@PatriciaShanahan: Да, я отредактировал свой ответ, чтобы указать и это. Ссылка на instanceof в вопросе вводит в заблуждение :( - person Jon Skeet; 19.09.2013

Я предполагаю, что предыдущих ответов Блэка, Макса и Джона достаточно для вашей части сравнения, поскольку «я не хочу, чтобы каждый компонент хотел сравнить список, но я хочу делегировать эту задачу AppMnger, потому что он тот, кто знает о компоненты, которые он создал. Эми подумала?» вы можете попробовать использовать шаблон дизайна посетителя.

person jay    schedule 19.09.2013