Zac Powell
Zac Powell

Reputation: 113

Check if Object is an instance of a class from a list of classes and cast

I have a number of classes that my object might be at run time. Currently to check which class it is i have a number of if statements like

    int id = 0;
    if (object instanceof Comment) {
        id = ((Comment) object).getId();
    }
    if (object instanceof Follow) {
        id = ((Follow) object).getId();
    }
    if (object instanceof Like) {
        id = ((Like) object).getId();
    }
    if (object instanceof Post) {
        id = ((Post) object).getId();
    }
    if (object instanceof User) {
        id = ((User) object).getId();
    }

This works but doesn't feel very clean. I had a look at Check if an object is an instance of any one of a list of classes (Android) which suggests a way to check if the object is an instance of a class from a list of classes like

if(myClasses.contains(obj.getClass())) {
   // obj is one of the classes I care about, so do something
}

However this doesn't then work as i need to go on and cast the object to that class.

Does anyone know of a cleaner way to bot check my object type is of a class from a list of classes AND then cast the object to that class.

Something like

if(myClasses.contains(object.getClass())) {
   ((CLASS_THAT_MATCHED) object).getId()
}

NOTE of course normally I would just make all of the Classes be subclasses of a super class that had the getID method and other methods I need. However in this specific instance these classes all need to be subclasses of a libraries class. Making them inherit from one base classes breaks code in the library. Which i know is a bad design issue on the libraries side but isn't something i can fix.

Upvotes: 2

Views: 1346

Answers (3)

Alberto
Alberto

Reputation: 12949

However in this specific instance these classes all need to be subclasses of a libraries class

Then you should use an interface:

public interface HasId{
   int /* or whatever type is the ID*/ getId();
}

public class Like extends LibrarySuperClass implements HasId{
   ...
}

However, if Like, Post etc are also library classes, you can do something like this:

// UNTESTED

Object obj =...;
List list = List.of(
  Like.class,
  Follow.class,
  Comment.class,
  User.class,
  Post.class,
);
Integer id = list
  .stream()
  .filter(class -> class.isInstance(obj))
  .map(class -> (Integer) class.cast(obj).getId())
  .findFirst()
  .orElse(null);

Upvotes: 4

You need to use polymorphism. For example, create an interface

public interface Message {
    int getId();
}

And let your classes implement it. Then you can call the getId method on each of them. Additionally, you can create an abstract class with basic functionality for the Post, Like, etc. classes. Something like that.

Upvotes: 2

Andrzej Więcławski
Andrzej Więcławski

Reputation: 99

Re @Alberto Sinigaglia solution,

it works excellent... but looks ridiculous after all necessary casts ;), ex:

    ...

    Object obj = new Comment();

    List<?> list = new ArrayList<>() {
        private static final long serialVersionUID = 4804401786243829831L;
        {
            add(Comment.class);
            add(Message.class);
            add(Post.class);
        }
    };

    Integer id = (Integer) list.stream().filter(c -> ((Class<?>) c).isInstance(obj))
            .map(c -> (Integer) ((I_ObjectType) ((Class<?>) c).cast(obj)).getObjectId()).findFirst().orElse(null);

    System.out.println("result?=" + id);

    ...

each Class implements:

public interface I_ObjectType {
    int getObjectId();
}

Upvotes: 0

Related Questions