java overloaded method
I have an abstract template method:
class abstract MyTemplate
{
pu开发者_开发问答blic 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,
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
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.
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.
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.
精彩评论