Sunday, 5 March 2017

java - How do I make the method return type generic?



Consider this example (typical in OOP books):



I have an Animal class, where each Animal can have many friends.
And subclasses like Dog, Duck, Mouse etc which add specific behavior like bark(), quack() etc.



Here's the Animal class:




public class Animal {
private Map friends = new HashMap<>();

public void addFriend(String name, Animal animal){
friends.put(name,animal);
}

public Animal callFriend(String name){
return friends.get(name);
}

}


And here's some code snippet with lots of typecasting:



Mouse jerry = new Mouse();
jerry.addFriend("spike", new Dog());
jerry.addFriend("quacker", new Duck());

((Dog) jerry.callFriend("spike")).bark();

((Duck) jerry.callFriend("quacker")).quack();


Is there any way I can use generics for the return type to get rid of the typecasting, so that I can say



jerry.callFriend("spike").bark();
jerry.callFriend("quacker").quack();


Here's some initial code with return type conveyed to the method as a parameter that's never used.




public T callFriend(String name, T unusedTypeObj){
return (T)friends.get(name);
}


Is there a way to figure out the return type at runtime without the extra parameter using instanceof? Or at least by passing a class of the type instead of a dummy instance.
I understand generics are for compile time type-checking, but is there a workaround for this?


Answer



You could define callFriend this way:




public  T callFriend(String name, Class type) {
return type.cast(friends.get(name));
}


Then call it as such:



jerry.callFriend("spike", Dog.class).bark();
jerry.callFriend("quacker", Duck.class).quack();



This code has the benefit of not generating any compiler warnings. Of course this is really just an updated version of casting from the pre-generic days and doesn't add any additional safety.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...