2

I have

interface FooI class FooA implements FooI class FooB implements FooI class FooC implements FooI 

I wrote a class "Handler" that has the following methods

static double handle(FooA f) static double handle(FooB f) static double handle(FooI f) 

and I have a function like the following:

void caller(FooI f) { Handler.handle(f); } 

with f just being known as a class implementing FooI. However f is an instance of FooA

Instead of calling the method for FooA, the method for FooI is called.

When I use f.getClass().getName() I get the correct class name (FooA).

I am confused because I expected the best-suited method to get called, namely the one for FooA.

I wanted to use the FooI method as a fallback to handle classes that could be implemented later, and I also want to handle f without having one big function where I am doing instanceof checks for all currently known classes implementing my interface.

What would be a good approach to do this?

1
  • Thanks for the additional tags, Samuel :-) Commented Jul 9, 2009 at 17:18

6 Answers 6

16

Overload resolution is done at compile time rather than execution time in Java. The signature was picked based on the compile-time type of your variable. Only overrides are determined at execution time.

A common solution for this in languages like Java is to use double dispatch and the visitor pattern.

Personally I'm not a huge fan of this. I prefer to try to design my way around it. That's not always possible, of course, but it's worth at least attempting.

Sign up to request clarification or add additional context in comments.

4 Comments

Just by curiosity...why don't you like these patterns ?
Thanks a bunch Jon! I totally forgot about the whole resolution issue.
@LB I can't vouch for Jon, but I personally find them to be rather ugly because now there's a bunch of indirection and boilerplate in front of what is, conceptually, a very straightforward operation.
It's amazing how often this question is asked and answered. I bet there have been at least a couple of hundred points in reputation score attributed to this question. I only got 10 of em :-(
3

You expect that the JVM seaches for the best fitting method at run time but that doesn't happen, actually. Instead the method to call is selected during compile time, when the only known information is that f is a class that implements FooI.

The best approach for that problem, the one that avoids the instanceof checks, might be moving the "handle" method into those classes FooA, FooB, FooI.

1 Comment

Thanks ammoQ! I totally forgot about that :-(.
1

I don't know exactly what your design is, but might the 'handle' functionality be better placed in your concrete FooI implementations?

1 Comment

Thanks teabot, that's how I implemented the whole thing in the end :-).
1

Java resolves which method to call at compile time using the reference type, which in your example is FooI - if you think about it this makes sense as the reference type is all it really has to go on at compile time.

Your Handler class doesn't handle(FooI f) and so as far as the compiler is concerned there is no valid handle method to call.

Comments

0

you should not use a static method for that, static methods obey to other rules than non final instance methods

1 Comment

The static-ness is irrelevant here. The point is that it's overload resolution which is taking place, not override resolution.
0

You could transform your interface into an abstract class, with a handler implementation. Then you implement it, and FooA and FooB overrides it

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.