I have the following interface and abstract class:
public interface DataExporter {
MultipartFile export() throws IOException;
}
public abstract class AbstractExporter<T> implements DataExporter {
protected abstract Iterable<T> getData();
}
I call getData()
method in my exporter class as shown below:
public class EmployeeExporter extends AbstractExporter<EmployeeDTO> {
protected Iterable<EmployeeDTO> getData() {
// code omitted
}
}
However, in another class e.g. ManagerExporter, I need to pass parameter to the getData()
method:
public class ManagerExporter extends AbstractExporter<ManagerDTO> {
protected Iterable<ManagerDTO> getData(UUID uuid) {
// code omitted
}
}
I think overloading that method in AbstractExporter
is not a good idea,
because in that case EmployeeExporter
will need to implement it even if it does not use it. So, what is the most proper approach to use getData()
method with & without parameter?
Note: I might also need other implementations that require multiple parameters e.g. protected Iterable<ManagerDTO> getData(UUID uuid, UUID departmentUuid, UUID staffUuid)
. In this case, should I need to use an Object array, etc. like Object[]
?
CodePudding user response:
If you need different method signatures, then you shouldn't extend the same abstract class.
So...just don't bother.
public class EmployeeExporter implements DataExporter {
protected Iterable<EmployeeDTO> getData() {
// code omitted
}
}
public class ManagerExporter implements DataExporter {
protected Iterable<ManagerDTO> getData(UUID uuid) {
// code omitted
}
}
CodePudding user response:
It depends on how you are going to use your DataExporter. If you want to use both methods of this class, then you have to add a method in all implementations, otherwise, you just do not need one of these methods in the parent class.
CodePudding user response:
You need to look at the code where you are calling getData()
.
In your original question you said "I call getData()
method in my exporter class as shown below". But what you show below is not a call, it's a concrete implementation of the abstract method.
The getData()
method is protected so it's only being called by AbstractExporter or its subclasses. Does AbstractExporter have at least one concrete method implementation that calls getData()
?
If not then you can simply remove getData()
from that abstract class. All calls to getData()
are in the sub-classes and they presumably know the right arguments to pass. The getData()
method can be removed from the abstract class and declared (possibly as private) in the concrete implementation classes.
If AbstractExporter contains calls to getData()
then how does it determine what arguments it should pass to that method? Something smells fishy. Instances of AbstractExporter can be used interchangeably. Each subclass should know how to perform getData()
using the same set of parameters. If ManagerExporter requires a UUID to perform its export then you could possibly assign that value when the instance is constructed rather than passing it as an argument to getData()
.
CodePudding user response:
If the parameterized versions getData(...)
can handle a beacon value safely and consistently, you could always implement a telescopic parameterless version in the abstract class, and only require the implementation of the parameterized version.
abstract class AbstractExporter<T> implements DataExporter {
protected final Iterable<T> getData() {
return getData(new UUID( 0 , 0 ));
}
protected abstract Iterable<T> getData(UUID uuid);
}