3

I have an abstract template method:

class abstract MyTemplate
{
    public void something(Object obj)
    {
        doSomething(obj)

     }

    protected void doSomething(Object obj);

}

class MyImpl extends MyTemplate
{

   protected void doSomething(Object obj)
   {
      System.out.println("i am dealing with generic object");
   }

   protected void doSomething(String str)
   {
      System.out.println("I am dealing with string");
   }
}


public static void main(String[] args)
{
   MyImpl impl = new MyImpl();
   impl.something("abc"); // --> this return "i am dealing with generic object"

}

How can I print "I am dealing with string" w/o using instanceof in doSomething(Object obj)?

Thanks,

2
  • 1
    From a OO perspective, I'd think hard, why I would need such a construct. Instances of class Object, don't have much of a behavior, why pass them as parameters? Commented Jan 9, 2011 at 18:18
  • Ditto what Horst said. If you are going to define your base class to work with the type "Object" in its method signatures, you really shouldn't assume handling a specific type. I'd suggest defining class hierarchy for MyTemplate with generics instead. Commented Jan 9, 2011 at 18:41

4 Answers 4

2

Well you really can't do it. Java can't do double dispatch out of the box. The problem is that the binding of the method calls is usually done mostly at compile time.

Here http://en.wikipedia.org/wiki/Double_dispatch

and here

http://www.javaperformancetuning.com/articles/ddispatch2.shtml

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

Comments

0

Its not possible. doSomething(Object obj) in MyImpl is the method that overrides the doSomething in MyTemplate.

Use the instanceof-operator in doSomething(Object obj) in MyImpl. It is better style anyway.

3 Comments

I think usage of instanceof, in general, hints to possible violations of Liskov Substitution Principle (LSP).
In this case the subclass seem to be "optimized" for a special type of objects, althought it is able to handle all. Ergo we need some distinguishment and this is done by instanceof. And also I don't like this principle, because subclassing something and using instead of the original object is IMHO a good way to alter a program. Maybe I just didn't understand the principle.
Polymorphism should be favored over instanceof for these types of things. Also, if you are checking for (and potentially casting to) a specific subtype within a method, then your method should have accepted the subtype as parameter and not the supertype (which can be accomplished by generics in the example the OP provided).
0

The java compiler uses the compile time type of the method arguments to create the method call, which in your example is Object and not String. The runtime type of the arguments is ignored by method calls.

You could either try the visitor pattern if you control all input classes or use reflection, which is slow/complex and easy to get wrong.

Comments

0

In short, you can't. Other answers explained why. An alternative might be to use generics instead and rely on a specific subtype of your abstract class for handling Strings (or another specific class). For example:

abstract public class MyTemplate<T> {
    abstract public void doSomething(T t);
}

public class MyTemplateImpl extends MyTemplate<Object> {

    @Override
    public void doSomething(Object o) {
        System.out.println("Dealing with a generic Object");
    }
}

public class MyTemplateImplForStrings extends MyTemplate<String> {
    @Override
    public void doSomething(String s) {
        System.out.println("dealing with a String");
    }
}

Which means your calling code would look like this:

MyTemplateImplForStrings template = new MyTemplateImplForStrings();
template.doSomething("hello");  //prints ""dealing with a String"

or

MyTemplate<String> template = new MyTemplateImplForStrings();
template.doSomething("hello");  //prints ""dealing with a String"

Note: you'll want to avoid using the abstract base as your reference type unless you parameterize it with String also; otherwise you'll leave the door open for ClassCastExceptions at runtime, which the compiler should warn you of.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.