Here is a very simple example:
private boolean f(List x) {
return x != null && !x.isEmpty();
}
private boolean f(Map x) {
return x != null && !x.isEmpty();
}
Code inside both function is same, they just operate on different objects. I want to merge them into one function to avoid code repeatation.
I tried something like:
private <T> boolean f(T x) {
return x != null && !x.isEmpty();
}
But it gives error on x.isEmpty()
Where the parts of what you want to use are covered by an interface implemented by both classes, use that interface.
But in your case, List and Map don't share an interface that provides isEmpty, so your options are:
Overloading (the following is your code unchanged)
private boolean f(List x) {
return x != null && !x.isEmpty();
}
private boolean f(Map x) {
return x != null && !x.isEmpty();
}
Accepting Object and using instanceof branches
private boolean f(Object x) {
// (roughly)
if (x == null) {
return false;
}
if (x instanceof List) {
return !((List)x).isEmpty();
}
if (x instanceof Map) {
return !((Map)x).isEmpty();
}
throw new IllegalArgumentException(); // Or whatever
}
Accepting Object and using reflection to get the isEmpty method (if any) and call it
private boolean f(Object x) {
// (roughly)
try {
return x != null && !(boolean)x.getClass().getMethod("isEmpty").invoke(x);
} catch (Exception e) {
throw new IllegalArgumentException(); // Or whatever
}
}
Of those, overloading seems the cleanest approach to me, not least because it gives you a compile-time error if you try to use f on a type it can't handle (whereas the others are runtime errors, blech), but it's (at least slightly) a matter of opinion.
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