8

I am trying to figure out how to get generics to jump through hoops.

I have:

interface Root { }
interface Middle extends Root { }
class Type implements Root { }

And many "Subtype" classes:

class Subtype1 extends Type implements Middle { }
class Subtype2 extends Type implements Middle { }
...

What I want is to declare a class with two type parameters T and S, where T is bound by Type and S is bound by T and Middle.

I can't see a way with generics to ensure that S extends T AND implements Middle. What I want is something like:

class Handler<T extends Root, S extends T, S extends Middle>;

or

class Handler<T extends Root, S extends <T extends Middle>>;

But of course neither are legal. Maybe there is some magic I am missing?

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Nick Palmer
  • 2,589
  • 1
  • 25
  • 34
  • 2
    You cannot do this. You can have multiple bounds but they must be 0-1 Class plus multiple interfaces. You cannot have a Generic type in a multiple bound situation. I suspect this restriction was kept because to allow type in multiple bounds would create a lot of complexity to the syntax checker, for what is a rare edge case. – BevynQ Mar 28 '13 at 00:06
  • 2
    related: http://stackoverflow.com/a/13261667/697449 – Paul Bellora Mar 28 '13 at 00:13
  • Thanks. That was my read as well but figured it was possible I was missing something in the spec. Casts it is! – Nick Palmer Mar 28 '13 at 00:29
  • Can you explain why declaring `Handler` isn't enough? The only difference is that `T` could possibly be a more specific type than `S`, that's it. – Paul Bellora Mar 28 '13 at 00:46
  • `Handler` means that Handler is bound to a single Subtype. I have several which means that Handler is no longer generic across Subtypes. In reality my code has half a dozen Subtypes which would mean an equal number of Handlers bound to the specific Subtype. – Nick Palmer Mar 28 '13 at 00:52
  • I made some edits to try and clarify your problem - could you please review my changes and let me know if anything is off? – Paul Bellora Mar 28 '13 at 01:03

2 Answers2

2

Try introducing an abstract class that extends SubType and implements Middle, so its type can be used in Handler.

abstract class MiddleSubtype extends Subtype implements Middle { }

Then,

class Handler<T extends Root, S extends MiddleSubtype> {  //...

EDIT: Following the update to the question, the same idea would look like:

abstract class MiddleType extends Type implements Middle { }

class Subtype1 extends MiddleType { }
class Subtype2 extends MiddleType { }
...

class Handler<T extends Root, S extends MiddleType> {  //...
Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
rgettman
  • 176,041
  • 30
  • 275
  • 357
  • 1
    Note that this is different from `T extends Root, S extends T ...` though, since `S` is no longer bound by `T`. – Paul Bellora Mar 28 '13 at 00:20
  • Yes and it ties Handler to one subtype. I actually have a bunch of subtypes which would mean a bunch of Handlers as well which is exactly what I was trying to avoid. – Nick Palmer Mar 28 '13 at 00:27
  • @NickPalmer See my edit to this answer - I think this is close to what rgettman was suggesting. – Paul Bellora Mar 28 '13 at 02:22
  • This does in fact work for the revised question posed and so I am accepting it. Unfortunately my real type hierarchy is even MORE complicated and so I am stuck with casting. Call it a case of over simplifying for the question and the restrictions on Generics being problematic. – Nick Palmer Mar 28 '13 at 02:42
  • @NickPalmer If you have time to put together a follow-up question, I'm sure people would be interested. – Paul Bellora Mar 28 '13 at 03:56
0

Or you could make S generic itself:

interface SInt<A,B> {}
class Handler<T extends Root, S extends SInt<T, Middle>>{}
janek
  • 184
  • 1
  • 6