So I am struggling to write this code in a clean way. I do not know if there is a better way.
private function1(Collection<D> collection) {
for (Iterator it = collection.iterator(); it.hasNext(); ) {
Object object = it.next();
switch (object .getClass().getSimpleName()) {
case "A": do some work with class A
break;
case "B": do some work with class B
break;
case "C": do some work with class C
break;
}
}
}
So I get a collection which I iterate. But the collection can be three different classes in the collection since class A,B,C are of the parent class D. I think my code is not clean and I am looking for a good way to write this. Here is another example that I have which is a bit different.
private function2(Collection<A,B,C> collection) {
for (Iterator it = collection.iterator(); it.hasNext(); ) {
Object object = it.next();
switch (object .getClass().getSimpleName()) {
case "A": do some work with class A
break;
case "B": do some work with class B
break;
case "C": do some work with class C
break;
}
}
}
In this function I can get either a collection of class A of class B or of class C. I though about making three separate functions for each class. But than I would have code duplicates. But I don't know if it would be actually better to split function2 into function2A, function2B, function2C.
Is there a better and cleaner way to implement those two functions. Classes A,B,C and D are from a framework. So I am unable to edit them.
You can create an interface that A, B, and C can implement from. In your interface you can declare a method that will 'do the work' and A,B, and C can have their own implementations.
interface MyInterface{
void doTheWork();
}
Then do this for each class
class A implements MyInterface {
void doTheWork() {
...
}
}
Now you can just loop through the collection without having to check what class the instance is of
EDIT - If you cannot modify A,B, or C than you can use a map with the class as the key and a lambda as the value.
//pseudocode
Map<Class<?>,Runnable> lambdaClassMap = new HashMap<>();
lambdaClassMap.put(A.class, () -> doAWork());
lambdaClassMap.put(B.class, () -> doBWork());
lambdaClassMap.put(C.class, () -> doCWork());
for(...) {
Object object = it.next();
lambdaClassMap.get(object.getClass()).run();
}
EDIT #2 - So since you want to access your object, instead of using Runnable
you can use Function
.
// change the function do what you want
// this one accepts the A object and calls an imaginary method 'getSize()'
Function<A, Integer> funcA = x -> x.getSize();
Map<Class<?>,Function> functionClassMap = new HashMap<>();
functionClassMap.put(A.class, funcA));
Now, you can use the apply()
method on your function to access your object directly when you are looping.
Integer size = functionClassMap.get(object.getClass()).apply(object);