Implied types
I have a family of Foo classes parametrized by a family of Tag classes:
publicclass Foo<Textends Tag>{}
and I wonder how best to declare a class Bar parametrized by some Foo: as
publicclass Bar<Fextends Foo><?extends Tag>>{}
or as
publicclass Bar<Textends Tag, Fextends Foo><T>>
In practice both lead to problems, although not the same ones.
[897 byte] By [
xolotla] at [2007-11-27 1:04:47]

# 1
Can you explain which problems you mean? Particularly what the disadvantage of declaring it the second way.
# 2
I tried so many things over the week-end I lost track of the particular corners I painted myself into but this is the issue: the way the system is designed there is a 1-to-1 correspondence between Foo and Tag classes, e.g., you have Foo1<Tag1>, Foo2<Tag2> etc and, e.g., Foo2<Tag1> and such like do not exist. The problem is that I can't express this; on the contrary, Foo2<Tag1> and so on are all possible type-wise.
The Tag classes are internal static classes of the Bar classes, e.g.,
public class Foo1<Tag1> {
private final Tag1 tag;
public Foo1(Tag1 tag) { this.tag = tag; }
public static class Tag1 {}
}
# 3
Ah, here it is: I just remembered the problem with the second way. Suppose I have a method that returns some random Bar (e.g., a parser of a string representation of Bar). Assuming I eschew the temptation to go for a raw type, then I have to declare the return type as
Bar<? extends Tag, ? extends Foo<? extends Tag>>
and how, then, do I express that although the Tag type may vary, for a given Bar instance it is the same Tag on both sides of the Bar parametrization? AFAICT the above form allows the Tag to the left and the Tag within Foo to vary independently. What I'd like to write, intuitively, is, e.g.,
<T extends Tag> Bar<T, ? extends Foo><T>> parse(String s);
i.e., to give the tag type a name, but this isn't valid syntax.
Now, if Bar is parametrized only over Foo or only over Tag then this problem does not arise but now I have the problem that one of the types in the pair is "hidden" and that I can't get at it: it isn't, by hypothesis, named in the Bar declaration and, as I said before, I don't know how to make Tag1 "magically" imply Foo1 and vice-versa, so that only one of them would suffice. It seems you need both to be named and then you run into the above problem. Gotcha.
# 4
> and how, then, do I express that although the Tag
> type may vary, for a given Bar instance it is the
> same Tag on both sides of the Bar
> parametrization? AFAICT the above form allows the Tag
> to the left and the Tag within Foo to vary
> independently.
I didn't see that coming. If it works as you believe it does, it definitely get's you stuck.
I believe you have tested this and it does allow these to vary independently but that doesn't seem correct to me. It would seem to violate the requirements of the Bar class declaration. Couldn't you write code where you would get classcastexceptions with this?
# 5
> I tried so many things over the week-end I lost track
> of the particular corners I painted myself into but
> this is the issue: the way the system is designed
> there is a 1-to-1 correspondence between Foo and Tag
> classes, e.g., you have Foo1<Tag1>, Foo2<Tag2> etc
> and, e.g., Foo2<Tag1> and such like do not exist. The
> problem is that I can't express this; on the
> contrary, Foo2<Tag1> and so on are all possible
> type-wise.
If there is such a connection, which only allows a 1-to-1 connection, then using Generics for the tag in Foo is quite pointless. Rethink your design.
# 6
> Couldn't
> you write code where you would get
> classcastexceptions with this?
OK, that doesn't make sense. Obviously, you can't instantiate a Bar using wildcards.
I just compiled this successfully in 1.6. Is this not what you said you want to do:
public class Foo<T extends Tag>
{
public static <T extends Tag> Bar<T, ? extends Foo><T>> test()
{
return null;
}
}
class Bar<T extends Tag, F extends Foo><T>>
{
}
class Tag {}
# 7
> If there is such a connection, which only allows a 1-to-1 connection, then using Generics
> for the tag in Foo is quite pointless.
I don't think so; if I knew of a better, non generics-encumbered design (I will note that you didn't offer any suggestion...) believe you me I would use it instead.
As I showed earlier, each Foo instance contains a Tag instance and I want to be able to write methods with signatures like
<T extends Tag> List<T> collecTags(List<? extends Foo<T> foos);
(going from Foo to Tag) or, conversely (from Tag to Foo):
<T extends Tag> Foo<T> resolve(T tag);
but unless Foo is parametrized over Tag, pray how am I going to get hold of the precise type of that Foo's Tag?
NB1: I must admit that my understanding of non-static inner classes is weak, though. Maybe there is a way down there that I cannot see.
NB2: Covariant return types can help here since Foo could have a Tag getTag(); method which Foo1 implements as Tag1 getTag(); Thus given a Foo1 you can get a Tag1 from the interface getTag w/o needing a cast and that clearly covers some of the same territory as generics. But if you all have is an unspecified Foo then how do you get hold of its precise Tag type so you can use it in method signatures and the like? I don't think you can.
# 8
> I just compiled this successfully in 1.6. Is this not what you said you want to do.
My, my. On the contrary it is what I wanted to write but, like I said, I thought it was not valid syntax. To be more precise I thought it did not make sense to have a type parameter T appear in a method signature that was not used in one of the method's parameters but only in its return type. I will try and report; for now all I can say is it compiles with 1.5, too.
# 9
> I don't think so; if I knew of a better, non
> generics-encumbered design (I will note that you
> didn't offer any suggestion...) believe you me I
> would use it instead.
I didn't offer suggestions, as I do not know about your real application code.
> <T extends Tag> List<T> collecTags(List<? extends
> Foo<T> foos);
As I have no idea, how and what for you are using that method, there is no way to say if this is useful. Is it an utility method or a method provided by Foo?
At least, it does not make sense to have List<? extends Foo<T>> as there can be no family of Foo<T> due to your requirement of Foo-Tag being one to one.
Would your using code have any advantage over returning a List<Tag>? According to your requirements, it already knows about what Foos it handles and thus the Tag associated with it. Or, if it is generic, it might not really need to know about it.
> <T extends Tag> Foo<T> resolve(T tag);
As there can only be one subclass of Foo for a tag T, you could as well pass the tag directly without the knowledge about its concrete type. Furthermore, this method implies there's only one instance of Foo for a tag, so a Map<Tag, Foo> could do for mapping from tag to foo.
> NB2: Covariant return types can help here since Foo
> could have a Tag getTag(); method which Foo1
> implements as Tag1 getTag(); Thus given a Foo1 you
> can get a Tag1 from the interface getTag w/o needing
> a cast and that clearly covers some of the same
> territory as generics. But if you all have is an
> unspecified Foo then how do you get hold of its
> precise Tag type so you can use it in method
> signatures and the like? I don't think you can.
Your applying code must have knowledge of the concrete Foo and Tag to make use of it, otherwise, if it is generic code, it does not have to know about it at all. As I have no idea about your use case, it's really barely possible to say, if generics are necessary here.
# 10
The problem with generifying an existing code bas is that it's more effort to determine when more precise typing really helps and were it is a mere annotation than if you were designing from scratch, "live", so I am trying to be as precise as possible. One must also keep in mind that a future Java release may outlaw raw types altogether (such a threat has been made, from people who matter, although I don't know if the threat is credible).
> At least, it does not make sense to have List<? extends Foo<T>> as there can be no family
> of Foo<T> due to your requirement of Foo-Tag being one to one.
Yes, in this particular method that was silly.
> Is it an utility method or a method provided by Foo?
Neither: collectTags it is a method from a class that acts as a store of foos.
> Would your using code have any advantage over returning a List<Tag>?
The tags are indeed all alike (mostly). The problem, as hinted with the resolve method, is you may want want to turn them back into foos, which are not all alike: besides some common methods, they carry subclass-specific ones as well. Thus I don't want to leak any type information in the round trip.
> Your applying code must have knowledge of the concrete Foo and Tag to make use of it, otherwise, if it is generic code,
The clients of the store who request, say, a List<Foo1> have indeed knowledge of the concrete type: the problem is how to make the store's own code as "clean" as possible. Maybe I should just give up, generify only the API and leave the store's implementation all "raw" (raw types, that is); in retrospect it certainly looks that way...
# 11
> The clients of the store who request, say, a
> List<Foo1> have indeed knowledge of the concrete
> type: the problem is how to make the store's own code
> as "clean" as possible. Maybe I should just give up,
> generify only the API and leave the store's
> implementation all "raw" (raw types, that is); in
> retrospect it certainly looks that way...
Well, I cannot tell what's appropriate. I just was giving some thoughts on what might help you deciding what you really need. I assume, each of your concrete Foo does implement some interface Foo, so it would be good to at least have List<Foo> instead of List.