1

I have just started using interfaces to implement listeners for asynchronous calls. Here is an example that executes a method when a database operation is complete.

//Interface
public interface DbOperationsListener {
    void dbOperationCompleted(Object value, int flag);
}

//Class that calls the listener
public class UserDbOps extends DbOps {
    private final UserDao dao;

    public UserDbOps(Activity activity, String databaseName, boolean singleUse) {
        super(activity, databaseName, singleUse);
        // in super class: this.listener = (DbOperationsListener) activity
        this.dao = database.userDao();
    }

    public void create(User user, int flag) {
        ExecutorService service = Executors.newSingleThreadExecutor();
        service.execute(() -> {
            listener.dbOperationCompleted(dao.create(user), flag);
            if (singleUse) database.close();
        });
        service.shutdown();
    }
}

//an example where it is used
public void dbOperationCompleted(Object value, int flag) {
    if (flag == RETRIEVE_USER) {
        user = (User) value;
        //use retrieved user
    }
}

As you can see I'm casting the resulting User from an object. Is there a way to provide the type of parameter to the interface, assuming I will use it for different types (other than User)? So that I can avoid casting the Object value to User or any other required type.

Gautham M
  • 4,816
  • 3
  • 15
  • 37
Joseph Sang
  • 310
  • 2
  • 9
  • 2
    It sounds to me like `DbOperationsListener` should be generic, with a type parameter indicating the expected type of "value". We can't really tell whether that's appropriate here or would cause other issues, but it's the first option I'd look at. – Jon Skeet Mar 15 '21 at 07:45
  • 1
    In a case you can't use a generics for some reason you can pass a class of the object as a parameter: `listener.dbOperationCompleted(dao.create(user), User.getClass(), flag)`. – Alex Sveshnikov Mar 15 '21 at 07:51

2 Answers2

1

You could specify a generic parameter.

The interface declaration could be :

public interface DbOperationsListener<T> {
    void dbOperationCompleted(T value, int flag);
}

And the implementation would be like:

public class DbOperationsListenerUserImpl implements DbOperationsListener<User> {
    @Override
    public void dbOperationCompleted(User value, int flag) {
        //.......
    }
}
Gautham M
  • 4,816
  • 3
  • 15
  • 37
  • This seems like the best way. Is it possible to implemet the same interface several times with different types? Like, 'DbOperationsListenerImpl implements DbOperationsListener, DbOperationsListener' and so on? – Joseph Sang Mar 15 '21 at 09:17
  • @JosephSang The interface is like a blue print. Multiple classes can implement the same interface like : `ClassA implement Listener` and `ClassB implements Listener` etc. – Gautham M Mar 15 '21 at 09:37
  • @JosephSang are you asking whether the same class could implement the same interface multiple times with different types? Then the answer is No. – Gautham M Mar 15 '21 at 09:41
-1

Found a solution. Turns out my question was wrongly worded, I could have found the solution if I searched for generics.

How to make a Java class that implements one interface with two generic types?

Joseph Sang
  • 310
  • 2
  • 9