Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force a generic type parameter to be an interface?

Is there a way in java to specify, that the type parameter of a generic class must be an interface (not just extending it!)

What I want to do is the following:

public class MyClass<X extends SomeInterface, Y extends SomeOtherClass & X> 

Meaning that Y must be a subclass of SomeOtherClass AND implement X. What I currently get by the compiler is

The type X is not an interface; it cannot be specified as a bounded parameter

So, how can I tell the compiler that X must always be an interface?

Edit:
OK, I guess I oversimplified my problem a bit. Let's use my actual application domain to make it more clear:

I have an API for representing diagrams. A Diagram contains Node and Edge objects. All these three classes implement the Shape interface. Shapes may have child shapes, a parent shape and belong to a diagram.

The thing is, that I need to make two versions of this API: one open-source with just basic functionality and an extended one with more features. However, the extended API must only provide methods, which return the extended types (ExtendedDiagram, ExtendedNode, ExtendedEdge and (here comes the problem) ExtendedShape).
So I have something like this:

/* BASIC CLASSES */ public interface Shape<X extends Shape<X,Y>, Y extends Diagram<X,Y>>{     public List<X> getChildShapes();     public X getParent();     public Y getDiagram();     ... }  public class Diagram<X extends Shape<X,Y>, Y extends Diagram<X,Y>> implements Shape<X,Y>{...} public class Edge<X extends Shape<X,Y>, Y extends Diagram<X,Y>> implements Shape<X,Y>{...} ...  /* EXTENDED CLASSES */ public interface ExtendedShape extends Shape<ExtendedShape,ExtendedDiagram> { ... }  public class ExtendedDiagram extends Diagram<ExtendedShape,ExtenedDiagram> implements ExtendedShape { ... } public class ExtendedEdge extends Edge<ExtendedShape,ExtenedDiagram> implements ExtendedShape { ... } ... 

The extended API works fine and the basic API code gives some warnings, but the main problem occurs when using the basic API:

public class SomeImporter<X extends Shape<X,Y>, Y extends Diagram<X,Y>, E extends Edge<X,Y>>{     private Y diagram;      public void addNewEdge(E newEdge){         diagram.addChildShape(newEdge);     ... 

That last line gives me the following warning:

The method addChildShape(X) in the type Diagram is not applicable for the arguments (E)

So now, I would just like to specify that E also needs to implement X and all would be fine - I hope ;)

Does all that make sense? Do you guys know a way to do that? Or is there even a better way to get the extended API with the said restrictions?
Thanks for sticking with me, any help is greatly appreciated!

like image 520
Philipp Maschke Avatar asked May 19 '11 16:05

Philipp Maschke


People also ask

Can a generic type be an interface?

Java Generic Classes and SubtypingWe can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.

How do you declare a generic interface?

Declaring Variant Generic Interfaces You can declare variant generic interfaces by using the in and out keywords for generic type parameters. ref , in , and out parameters in C# cannot be variant. Value types also do not support variance. You can declare a generic type parameter covariant by using the out keyword.

Can type parameters be used with interfaces?

When an interface is specified as a constraint on a type parameter, only types that implement the interface can be used. The following code example shows a SortedList<T> class that derives from the GenericList<T> class. For more information, see Introduction to Generics.


1 Answers

You can use:

class Foo<T extends Number & Comparable> {...} 

A class Foo with one type parameter, T. Foo must be instantiated with a type that is a subtype of Number and that implements Comparable.

like image 116
idichekop Avatar answered Sep 23 '22 10:09

idichekop