For the method below, is there a better way of building the returned object?
It's of type <T>
.
The first input
parameter has the same type as the returned object.
The last builder
parameter is what makes me anxious.
It currently points to a static factory method in each T class.
If you wanted to avoid passing the builder
param, how would you handle that?
(I would prefer not to resort to a cast, and to use a technique that is friendly towards immutable objects.)
public <T extends FourVector> T transformVector(T input, TransformInto direction, Function<Map<Axis, Double>, T> builder) {
//the core calculation uses matrices, so we convert back and forth like so
Matrix input_matrix = Matrix.asMatrix(input);
Matrix result = physicsMatrix(direction.sign()).times(input_matrix);
//I need to build a new T object here; hence the builder param
return builder.apply(asComponents(result));
}
I experimented with about 6 different variations.
The best I could come up with involves creating an explicit Builder
interface for building the desired object.
The basic idea is that the incoming input
object is of the correct type T already, so it makes sense to ask that object to build a new object of the same type T.
private <T extends FourVector & Builder<T>> T transformVector(T input, TransformInto direction) {
//the core calculation uses matrices, so we convert back and forth like so
Matrix input_matrix = Matrix.asMatrix(input);
Matrix output_matrix = lambdaMatrix(direction.sign()).times(input_matrix);
return input.build(fromComponents(output_matrix));
}
With the Builder
interface as the translator from the lower-level data structure to the desired higher-level data structure:
public interface Builder<T> {
/** Build a new T object out of the given components. */
public T build(Map<Axis, Double> components);
}
The unusual thing about this is that object creation is not through a constructor, but through a regular object method.