Search code examples
javainterfacecomparedelegationinstanceof

How can I compare objects using instanceof but Interface types (not passing exact class name.)


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 ;
}

In Above code AppMnger is having a list of components. Components are communicating each other. So if one component want to know another component instance it call the AppMnger getComponent(comp) method. But I get an error when I use instanceof operator. I don't want each component to want compare the list but I want to delegate that task to AppMnger because he is the one who knows about components it created. Amy thought?


Solution

  • I think you should redesign getComponent to take a Class<? extends Component> rather than a Component. Then you can use 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.
    }
    

    And SomeComponent would use:

    appManager.getComponent(SomeComponent.class);
    

    If you really wanted to use an instance, you could overload the method like this:

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

    EDIT: If you actually only want to check for the exact class, you don't want instanceof-like behaviour - you just want:

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

    I would still suggest using this method signature though - it would feel very odd to have to already have an instance of a component in order to find a component of the type you want.