0

Is it possible in Java to do a kind of dynamically dispatch a method based on the runtime type of an object?

Defining the following hierarchy:

public abstract class AbstractError {...}

public class GenericError extends AbstractError {...}

public class ValidationError extends AbstractError {...}

Would it be possible to have a method invocation that relies on actual runtime type of AbstractError object such as the following (which seems not work)?

public foo() {
    AbstractError error = ....
    // Here I want to decide which method to invoke on runtime (based on error concrete type)
    MessageItemDTO = buildMessageItem(error);
}

private MessageItemDTO buildMessageItem(GeneralError error) {
    // ... call here when error (declared AbstractError) is actually a GeneralError
}

private MessageItemDTO buildMessageItem(ValidationError) {
    // ... call here when error (declared AbstractError) is actually a ValidationError
}

private MessageItemDTO buildMessageItem(AbstractError error) {
    throw new UnsupportedOperationException("No dispatcher implemented for type: " + error.getClass().getSimpleName());
}

Is it possible to achieve this or something similar in Java?

Gerard Bosch
  • 648
  • 1
  • 7
  • 18
  • 2
    Conceptually, you want to apply the visitor pattern here. – Oliver Charlesworth Jul 04 '17 at 11:56
  • Conceptually you want to move the logic in the `buildMessageItem()`methods into the respective `*Error` class. (which is called *polymorphism* BTW... – Timothy Truckle Jul 04 '17 at 12:02
  • 2
    Dynamic dispatch in Java is based on actual type of an object whose method is being called. Method arguments are not polymorphic. Ideally you should do what @TimothyTruckle suggested - every error should know how to create respective MessageItemDTO – Dima Ogurtsov Jul 04 '17 at 12:14
  • @DmitryOgurtsov , TimothyTruckle , doing this I would introduce high coupling between Error and DTO. Wouldn't it? I think Error shouldn't know any about MessageItemDTO. I will try to figure how to make use of visitor to achieve what I want as Oliver suggested (though I don't know how for now...) – Gerard Bosch Jul 04 '17 at 13:16
  • @OliverCharlesworth thanks for the tip, I didn't get the point to the visitor. But what I don't like of visitor is that visited classes must implement an accept() method what is very ugly. I know that using reflection you can get rid of accept methods but not sure if doing this way is a performance penalty. – Gerard Bosch Jul 04 '17 at 13:41
  • @GerardB - You basically have three options, each of which has downsides. (1) Polymorphism - downside is that you may be loading up your `Error` classes with unrelated concerns. (2) Visitor pattern - downside is the `accept` mechanism. (3) Reflection - downside is you step outside the compiler and all of its protection. – Oliver Charlesworth Jul 04 '17 at 13:56
  • Given this particular case, could someone briefly indicate me if using `instanceof` with `if-else` fork would be justified given the added complexity of using the visitor approach? Does visitor worth in front of the simplicity of `instanceof` approach? I know `instanceof`is not a good practice BTW. – Gerard Bosch Jul 10 '17 at 16:33
  • @OliverCharlesworth I finally solved it with a visitor, but I'm still thinking about the previous comment: Would it be a good design to implement it using `instanceof` operator with an `if-else` to avoid the visitor's overhead? It seems I introduced a lot of complexity with the visitor and I'm thinking if a simplier implementation using `instanceof` would be acceptable and the tradeoffs from the design point of view. Thx!! – Gerard Bosch Aug 07 '17 at 16:46
  • Please, as per my previous comment: What about the trade offs of using `instanceof` construct (if any) vs. visitor for a concrete case like this? Asking from a design standpoint. – Gerard Bosch Feb 08 '18 at 12:07

0 Answers0