If I have multiple implementations of a method, one of which takes an instance of a particular class, the other a superclass of it, how can I force the most specific one to be called?
Let us take the following code:
public static class Cat {};
public static class DomesticCat extends Cat {};
public static class Lion extends Cat {};
public static class CatOwner {
public Cat cat;
}
public static void identifyCat(Cat cat) {
System.out.println("Generic cat");
}
public static void identifyCat(Lion lion) {
System.out.println("Lion");
}
Now if I do:
identifyCat(new Cat());
identifyCat(new Lion());
identifyCat(new DomesticCat());
I get:
Generic cat
Lion
Generic cat
So far, so good, Java picks the most specific one—except that matching is done based on the declared class (or whatever I cast it to), not the actual one. For example, the following code:
Cat simba = new Lion();
identifyCat(simba);
calls identifyCat(Cat)
, not identifyCat(Lion)
—because simba
is declared as Cat
.
For a more realistic use case, let us assume that Cat
and all its subclasses are defined in an external library (which I have no control over), and I get a Cat
instance from there with no control over the actual class of the instance, like:
Cat cat = CatFactory.getCat();
identifyCat(cat);
This will always call identifyCat(Cat)
, even if the Cat
instance returned is of type Lion
.
Considering I might have more implementations for identifyCat()
, and they do more than just identify the instance (they might, for instance, interact with members introduced by that particular subclass): is there an easy way to get my code to call identifyCat(Lion)
for a Lion
(even if declared as Cat
), without resorting to enumerative if
statements à la if (cat instanceof Lion) identifyCat((Lion) cat)
?