In Java, how do we make a type parameter of a generic to take a type parameter itself? What I would really like to do is the following:
public class TransformerBase<T, TRANSFORMER<U> extends TransformerBase<U, TRANSFORMER>>
{
public <O> TRANSFORMER<O> transform1(TransformFunction<T, O> f)
{
...
}
}
And one would extend the TransformerBase class and add their own transform methods, while retaining the original transform methods in the base class, like this:
public class MyTransformer<T> extends TransformerBase<T, MyTransformer>>
{
public <O> MyTransformer<O> transform2(TransformFunction<T, O> f)
{
...
}
}
Then the user of the class can chain the method calls like this:
MyTransformer<String> input = new MyTransformer<>();
MyTransformer<String> result = input
.transform1(new TransformFunction<String, Integer>() {...})
.transform2(new TransformFunction<Integer, String>() {...});
This is similar to the problem outlined here but with the addition that the "Builder" itself takes a type parameter.
But the thing is, it does not look like Java supports this kind of construct. Is there another way to solve this problem?
I tried declaring the base class like this:
public class TransformerBase<T, TRANSFORMER extends TransformerBase<T, TRANSFORMER>>
{
public <O, TFM_OUT extends TransformerBase<O, TFM_OUT>> TFM_OUT transform1(TransformFunction<T, O> f)
{
...
}
}
And the extended class:
public class MyTransformer<T> extends TransformerBase<T, MyTransformer<T>>
{
public <O, TFM_OUT extends MyTransformer<O>> TFM_OUT transform2(TransformFunction<T, O> f)
{
...
}
}
The user can do this:
MyTransformer<Integer> input = new MyTransformer<>();
MyTransformer<String> t = input.transform1(new TransformFunction<Integer, String>(){...});
MyTransformer<Integer> result = t.transform2(new TransformFunction<String, Integer>(){...});
But in order for method chaining to work, the caller has to declare the type parameters explicitly, which kind of defeats the purpose of chaining:
MyTransformer<String> result = input
.<String, MyTransformer<String>>transform1(new TransformFunction<Integer, String>(){ ... })
.transform2(new TransformFunction<String, Integer>(){...});