I have a fairly complicated set of generic classes in Java. For example, I have an interface
interface Doable<X,Y> {
X doIt(Y y);
}
and the implementation
class DoableImpl implements Doable<Foo<Bar<Baz,Qux>>,Foo<Bar<Zot,Qux>>> {
Foo<Bar<Baz,Qux>> doIt(Foo<Bar<Zot,Qux>> fooBZQ) { ... }
}
In the real implementation, Doable
has quite a few methods and so Foo<Bar<Baz,Qux>>
, etc., appear over and over again.
(Believe it or not, the generic types are quite a bit more painful than this. I've simplified them for the example.)
I'd like to simplify these, to save myself typing and to ease the strain on my eyes. What I'd like is to have a simple "type alias" for Foo<Bar<Baz,Qux>>
, etc., say FooBBQ
and FooBZQ
.
My current idea is to define wrapper classes:
class FooBBQ {
public static FooBBQ valueOf(Foo<Bar<Baz,Qux>> fooBBQ) {
return new FooBBQ(fooBBQ);
}
private Foo<Bar<Baz,Qux>> fooBBQ;
private FooBBQ(Foo<Bar<Baz,Qux>> fooBBQ) {
this.fooBBQ = fooBBQ;
}
public Foo<Bar<Baz,Qux>> toGeneric() {
return fooBBQ;
}
}
class FooBZQ { /* pretty much the same... */ }
class DoableImpl implements Doable<FooBBQ,FooBZQ> {
FooBBQ doIt(FooBZQ fooBZQ) { ... }
}
This works well, but it has a few drawbacks:
- We need to define separate wrappers for each generic instance. The wrapper classes are short and stylized, but I can't figure out a way to macro-ize them.
We have the translation overhead (conceptually, if not operationally) of calling
valueOf
andtoGeneric
to convert betweenFooBBQ
andFoo<Bar<Baz,Qux>>
. For example, ifdoIt
calls into some library routine that expects aFoo<Bar<Zot,Qux>>
(which the real implementation does), we end up with something likereturn FooBBQ.valueOf( libraryCall( fooBZQ.toGeneric() ) )
where we would originally have had
return libraryCall(fooBZQ);
Is there some other way to get the "type alias" behavior I want here? Perhaps using some third-party macro toolset? Or do I need to accept that I'm going to have to do a lot of typing, one way (using the generic types in the implementation) or the other (writing wrappers for them)? Maybe having this many generic parameters flying around is just a bad idea and I need to re-think the problem?
[UPDATE] OK, I'm banning any further "don't do that" answers. Take it as a given that Foo<Bar<Baz,Qux>>
has genuine value in my problem domain (Pete Kirkham may be right that it has enough value to get a proper wrapper class with a descriptive name). But this is a programming problem; don't try to define the problem away.