Search code examples
javaabstract-classinstanceofabstract-data-type

How can I identify the class of an abstract object being an argument to a function?


I am trying to make a function that sifts through an array of objects that inherit from one abstract class. The function takes in the item to look for as an argument of the abstract class type, and, if it finds the object type, it deletes it. Here is the code:

public void removeItem(MPItem itemDelete){
    for (int i = 0; i < myItems.length; i++){
        if(myItems[i] instanceof itemDelete){
            myItems[i] = null;
            break;
        }
        
        //If it reaches this point, we hit the end of the array with no item matching.
        if(i == myItems.length - 1){
            System.out.println("Item to delete not found");
        }
    }
}

I know that by typing instanceof in the if statement, it tries to find a class named itemDelete, which does not exist. I am trying to make it to where, no matter what item type I pass in the function that are children of the MPItem abstract class, it will see what exact child class it is, find the first instance of that child type in the array, set it to null, and exit the function. Can anyone help with this or direct me to something that will? Thanks!


Solution

  • Assuming that myItems is defined like this:

    MPItems[] myItems = ...
    

    You can use generics and the isAssignableFrom method to achieve your goal:

    public void removeItem(Class<? extends MPItem> itemDelete){
        for (int i = 0; i < myItems.length; i++) {
            if (myItems[i].getClass().isAssignableFrom(itemDelete)){
                myItems[i] = null;
                break;
            }
    
            //If it reaches this point, we hit the end of the array with no item matching.
            if (i == myItems.length - 1){
                System.out.println("Item to delete not found");
            }
        }
    }
    

    To call the function, do this:

    foo.removeItem(Something.class);
    

    Side note: myItems[i] = null is not actually deleting anything from the array (at least not in the normal sense). It is simply setting that position in the array to be null (maybe this is actually what you want). If you actually want to remove the element from the array, here is an alternative solution:

    public void removeItem(Class<? extends MPItem> itemDelete){
        myItems = Stream.of(myItems).filter(i -> !i.getClass().isAssignableFrom(itemDelete)).toArray(MPItem[]::new);
    }
    

    However, since this method is reassigning myItems, it may break other parts of your code :/