I would like to perform several operations based on the type of an object and without using instanceof
. At first I was thinking of overloading methods based on types (as seen below), and thought that maybe Java would choose the method appropriately (based on most specific class of object).
import java.util.ArrayList;
import java.util.List;
public class TestA {
public static void main(String[] args)
{
List<Object> list = new ArrayList();
list.add(new A());
list.add(new B());
list.add(new C());
list.add(new Object());
TestA tester = new TestA();
for(Object o: list)
{
tester.print(o);
}
}
private void print(A o)
{
System.out.println("A");
}
private void print(B o)
{
System.out.println("B");
}
private void print(C o)
{
System.out.println("C");
}
private void print(Object o)
{
System.out.println("Object");
}
}
class A {
}
class B extends A {
}
class C {
}
The output is:
Object
Object
Object
Object
However the output I'm after is:
A
B
C
Object
instanceof
visitor.accept(this)
in class A
causes the function visitor.accept(A o)
be called.instanceof
because I've read using it is bad practice; in this case, would it still be bad practice?Java supports method overloading through two mechanisms: By changing the number of parameters. By changing the data type of parameters Overloading by changing the number of parameters A method can be overloaded by changing the number of parameters.
No, you cannot overload a method based on different return type but same argument type and number in java.
Well my answer would be to make classes A,B and C implement a common interface.
And then each of them can have their own specific implementations of this interface.
This way, you can call the same method for all the objects(thus avoiding overloaded methods), and also ensure custom functionality based on the type of the object(i.e the class from which it was instantiated).
This answer considers that modifying given classes and their relationship is not an option.
Is there a way to make Java choose the method based on the most specific type of the parameter object?
Java compiler cannot cast this for you because maybe that's not what you want (in your case that's what you want, but maybe other people don't want this behavior and they would be no solution for them). Since you're passing an Object
reference to print()
, the compiler will call print(Object)
.
If not, what alternatives can I look at for such functionality, without the aid of instanceof
You can wrap your Object
with its type in a wrapper class, e.g.:
public class ObjectWrapper {
private final Object object;
private final int type;
}
This way you can safely cast to the type of the Object
without using instanceof
. Although this IMHO is more complicated than simply using instanceof
, and actually it only creates your own instanceof
...
I'm honestly against instanceof because I've read using it is bad practice; in this case, would it still be bad practice?
In programming, nothing is always a bad practice. Everything depends on the situation. In this situation I think you can use instanceof
and do unsafe casting because the design requires so. And anyway, if instanceof
operator exists in the language, is because it's used. If instanceof
was always a bad practice, it wouldn't exist as part of the language. See this and this.
I was actually trying to simulate the visitor pattern however it seems, what makes visitor pattern work is because of the double dispatch, which makes the parameter being "accepted" be in the correct type during function call, particularly, visitor.accept(this) in class A causes the function visitor.accept(A o) be called.
Check my second link for cons on using the visitor pattern.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With