Nesting generics into generics - java

Lets say I have 2 interfaces which define some kind of container format holding a specific type of data.
public interface Content {
}
public interface Holder1<T extends Content> {
}
public interface Holder2<T extends Content> {
}
Now I want some converter which defines objects that can transform an object of type Holder1 into an Holder2.
This converter should keep information about the kind of objects stored within the original object:
public interface ConverterPrototype1 {
public <U extends Content> Holder2<U> convert(Holder1<U> source);
}
But I also want to be able to restrict the type of Holder1 that some converter can work on:
interface ConverterPrototype2<U extends Content, V extends Holder1<U>> {
public Holder2<U> convert(V source);
}
Is there a way to combine the semantics of these 2 interfaces into a single one? Something like
//INVALID CODE!
interface CombinedConvertor<V extends Holder1> {
public <U extends Content> Holder2<U> convert(V<U> source);
}
I'm not sure if my title is suited for this problem, but I couldn't find a better description... Similar problems posted here always seemed to talk about different things.
Edit:
After stumbling upon this link, I came up with following code. It is still invalid, but closer to actual java code.
//INVALID CODE!
interface CombinedConvertor<X extends Source<?>> {
public <U extends Content, V extends X & Source<U>> Target<U> convert(V source);
}

It is possible to create a CombinedConvertor interface, as long as you define another generic type parameter to represent the single generic type parameter of Holder1, as you already have done to ConverterProptotype2. This removes the generic type parameter from the convert method and adds it to the interface itself.
interface CombinedConvertor<U extends Content, V extends Holder1<U>> {
public Holder2<U> convert(V source);
}

If I'm understanding what you're asking, and from your comment to the other answer ... you can infer both.
public interface Converter
{
public <U extends Content, V extends Holder1<U>> Holder2<U> convert(V source);
}

After finding the format of code posted in my edit, I found many related items talking about this problem. It appears the java language simply does not support this case. I can recommend this post to learn more about the details of this limitation.

Related

Generics where you already know the type of the generic type?

Given the following interface:
Interface Executor<T extends Form>
{
public Result execute( Request<T> request);
}
as well as a number of implementations of this interface, such as:
LoginExecutor,
AddContactExecutor, etc.
For each implementation, I know exactly what the value of T is going to be.
E.g, for LoginExecutor, T will be LoginForm extends Form, etc.
What's the conventional way of defining my implementations in such a case? If I do:
public LoginExecutor<LoginForm> implements Executor<LoginForm>
{
public Result execute(LoginForm request) {...}
}
that gives me an error. So I'm doing the following:
public LoginExecutor<T extends LoginForm> implements Executor<T>
{
public Result execute(T request) {...}
}
and that seems to be working, however I'm wondering if there is a a better / more conventional way of doing this.
Typically if you know the types of the generic you can just do the following:
public LoginExecutor implements Executor<LoginForm>
{
public Result execute(LoginForm request) {...}
}
as the name suggests this approach is used for generic programming. When the type is know and you want to use for a particular type, you just implement using the type and from generic it becomes specific.

Bound mismatch with Java Generics "nesting"

I'm having difficulty using generics for a redesign/refactoring I'm doing on an existing design.
public interface DataDto {
// some data here
}
public interface SetDto<MyDataDto extends DataDto> {
List<MyDataDto> getData();
}
public interface Results<MySetDto extends SetDto<DataDto>> {
MySetDto getResults();
}
public interface MyProblemInterface<MyDataDto extends DataDto,
MySetDto extends SetDto<MyDataDto>,
MyResults extends Results<MySetDto>> {
// some stuff here
}
My problem is that I get the following error for MyProblemInterface:
Bound mismatch: The type MySetDto is not a valid substitute for the
bounded parameter <MySetDto extends SetDto<DataDto>> of the type
Results<MySetDto>
I admit my experience with generics is somewhat limited, but basically I'm trying to enforce that all three of the types in MyProblemInterface are the same "type". For example, if I have ADataDto, BDataDto, ASetDto<ADataDto>, BSetDto<BDataDto>, AResults<ASetDto>, BResults<BSetDto>, I want to ensure a class can't implement MyProblemInterface in a manner like AMyProblemInterface<ADataDto, ASetDto, BResults>. I would think that since MySetDto extends SetDto<MyDataDto> just fine, I could continue to take that further, but I'm apparently wrong.
Thank you for any help.
You want too much from Java generics.
It would be simpler to declare your interface as following:
public interface MyProblemInterface<MyDataDto extends DataDto>
And then force method to use SetDto<MyDataDto> and Results<MySetDto>.
By using generics in class/interface declaration you specify some kind of variety which is determined later in definition. But in your case you said that SetDto and Results will always have MyDataDto as parameter, so there is no variety.
Shouldn't it be something like this instead, and you add the actual classes only when implementing the interfaces.
Updated the code, because I forgot to add the right Results definition. This should work.
public interface DataDto {
// some data here
}
public interface SetDto<T extends DataDto> {
List<T> getData();
}
public interface Results<T extends SetDto<? extends DataDto>> {
T getResults();
}
public interface MyProblemInterface<T extends DataDto, E extends SetDto<T>, K extends Results<E>> {
// some stuff here
}

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!
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.
In the generics context, <Type extends IInterface> handles both extends and implements. Here's an example:
public class GenericsTest<S extends Runnable> {
public static void main(String[] args) {
GenericsTest<GT> t = new GenericsTest<GT>();
GenericsTest<GT2> t2 = new GenericsTest<GT>();
}
}
class GT implements Runnable{
public void run() {
}
}
class GT2 {
}
GenericsTest will accept GT because it implements Runnable. GT2 does not, therefore it fails when trying to compile that second GenericsTest instantiation.
Maybe you can simplify your model a bit: too much generics become quickly a real pain in terms of readability, and that's quite an issue if you define a public API. Usually, if you can't understand anymore what should be inside the brackets, then you're going too far for your need - and you can't expect users to understand it better than yourself...
Anyway, in order to make your code compile, you may try defining something like this, in the Shape type:
public <S extends Shape<?,?>> void addChildShape(S shape);
That should do it.
HTH
You wrote the following:
public interface Shape<X extends Shape<X,Y>, Y extends Diagram<X,Y>>{
public List<X> getChildShapes();
public X getParent();
public Y getDiagram();
...
}
I would advise, at the minimum, getting rid of the X type variable, as follows:
public interface Shape<Y>{
public List<Shape<Y>> getChildShapes();
public Shape<Y> getParent();
public Diagram<Y> getDiagram();
...
}
The reason being is that what you originally wrote suffers from a potentially unbounded recursive nesting of the type parameters. A shape may be nested within a parent shape, which may be nested within another, all of which must be accounted for in the type signature... not a good recipe for readability. Well, it doesn't happen quite that way in your example, in which you declare "Shape<X>" instead of "Shape<Shape<X>>" but that's the direction you're going in, if you ever wanted to actually use Shape on its own...
I would probably also recommend going one step further and getting rid of the Y variable for similar reasons. Java generics don't cope very well with this sort of composition. When attempting to enforce static types for this type of modelling via generics, I've found that the type system starts to break down when you start to extend things later on.
It's typical of the Animal/Dog problem... Animal has a getChildren(), but Dog's children must also be Dogs... Java doesn't cope with this well because (in part due to the lack of abstract types as in languages like Scala, but I'm not saying you should rush off and use Scala for this problem either) the type variables have to start being declared in all sorts of places where they don't really belong.
Use a pre-processor to generate the "reduced" version of your code. Using apt and annotations might be a nice way to do it.
I might be WAY off base here, but my understanding of generics is a little different.
I am asking someone to correct me if I am wrong.
IMO -
This is a very confusing structure that you have. You have SubClasses of Shape being referenced infinitely it looks like.
Your Shape interface is utilized in the same manner as a HashMap, but I have never seen a HashMap do what you are trying to do, eventually you have to have X be a class in Shape. Otherwise you are doing HashMap
If you always want X to be a "IS A" relationship to an interface it won't happen. That is not what generics are for. Generics are used to apply methods to multiple Objects, and interfaces cannot be Objects. Interfaces define a contract between a client and a class. All you can do with the is say that you will accept any Object that implements Runnable, because all or some of your methods are required to utilize the Runnable interface methods. Otherwise if you don't specify and you define as , then your contract between your class with the client can produce unexpected behavior and cause either the wrong return value or an exception to be thrown.
For example:
public interface Animal {
void eat();
void speak();
}
public interface Dog extends Animal {
void scratch();
void sniff();
}
public interface Cat extends Animal {
void sleep();
void stretch();
}
public GoldenRetriever implements Dog {
public GoldenRetriever() { }
void eat() {
System.out.println("I like my Kibbles!");
}
void speak() {
System.out.println("Rufff!");
}
void scratch() {
System.out.println("I hate this collar.");
}
void sniff() {
System.out.println("Ummmm?");
}
}
public Tiger implements Cat {
public Tiger() { }
void eat() {
System.out.println("This meat is tasty.");
}
void speak() {
System.out.println("Roar!");
}
void sleep() {
System.out.println("Yawn.");
}
void stretch() {
System.out.println("Mmmmmm.");
}
}
Now if you did this class you can expect that you CAN always call 'speak()' & 'sniff()'
public class Kingdom<X extends Dog> {
public Kingdom(X dog) {
dog.toString();
dog.speak();
dog.sniff();
}
}
However, if you did this you CANNOT ALWAYS call 'speak()' & 'sniff()'
public class Kingdom<X> {
public Kingdom(X object) {
object.toString();
object.speak();
object.sniff();
}
}
CONCLUSION:
Generics give you the ability to utilize methods on a wide range of objects, not interfaces. Your final entry into a generic MUST be a type of Object.
The reserved word “extends” as along with a type parameter T is used to specify a bound.
‘…in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces).’
[ https://docs.oracle.com/javase/tutorial/java/generics/bounded.html ]
In short, “extends” can only be used to specify a bound (whether a class or an interface) for some class type parameter T and not any interface type parameter T.
In your case,
public class MyClass<X extends SomeInterface, Y extends SomeOtherClass & X>
The compiler resolves X to be a class. For the second occurrence of X along with the type parameter Y (which clearly needs to be a class anyway), it requires X to be an interface. Since it has already resolved X to be class, it signals the error for the second occurrence of X,
The type X is not an interface;
Further, had X been specified in the first occurrence as an unbounded parameter, the compiler would have resolved it to be either a class or an interface and it would’ve considered the second occurrence of X to be a possible interface and thus allowed compilation. Since it was not so, the compiler clarifies,
it cannot be specified as a bounded parameter

problem with wildcards and one class which implements two interfaces

I have this question.
I have class UserImpl implements MyUser, YourUser
and class UsersGetterImpl implements MyUsersGetter, YourUsersGetter.
I want to implement a method inside UsersGetterImpl, which returns
List<MyUser> getUsers() for MyUsersGetterinterface, and
List<YourUser> getUsers() for YourUsersGetterinterface, but I cannot understand what have to be the return type of getUsers() inside the UsersGetterImpl class - probably it has to be something with wildcards (like List<? extends UserImpl> getUsers(), but not exactly, because this example won't work...)
It is hard to tell what you are asking, but according to the Java Language Specification:
In a situation such as this:
interface Fish { int getNumberOfScales(); }
interface StringBass { double getNumberOfScales(); }
class Bass implements Fish, StringBass {
// This declaration cannot be correct, no matter what type is used.
public ??? getNumberOfScales() { return 91; }
}
It is impossible to declare a method named getNumberOfScales with the same signature and return type as those of both the methods declared in interface Fish and in interface StringBass, because a class can have only one method with a given signature (§8.4). Therefore, it is impossible for a single class to implement both interface Fish and interface StringBass.
However, if both of your interfaces specify the same return type, then you can go ahead and implement that method. If MyUser and YourUser have a common ancestor then you could do List<? extends User> or if they have no commonality you can use simply use List<?>.
At that point though, you have to stop and consider if a common implementation is what you actually want. I suspect there may be a more elegant solution, if you provided us with more details about your problem.
Edit:
Based on your comment, you want something like...
interface MyUserGetter { List<? extends MyUser> getUsers(); }
interface YourUserGetter { List<? extends YourUser> getUsers(); }
class UserGetterImpl { List<? extends UserImpl> getUsers(); }
This is untested, and I'd guess has a 50% chance of working.
The architectural suggestion is that instead of having a single implementation for two interfaces you might actually want two implementations of one interface:
interface User {}
class MyUser implements User {}
class YourUser implements User {}
interface UserGetter { List<? extends User> getUsers(); }
The short answer is: it can't be done. You cannot have two methods whose signature differs only by return type, and you therefore cannot have one class implement two interfaces that define methods that only differ by return type.
The easy fix is to make MyUsersGetter and YourUsersGetter have methods with different names.
One possible workaround would be to have UsersGetterImpl not implement MyUsersGetter and YourUsersGetter directly, but to have delegates:
class UsersGetterImpl {
public MyUsersGetter getMyUsers () {
return new MyUsersGetter () {
public List<MyUsers> getUsers () {
//do stuff here
}
}
}

Need derived class for java generics declaration

I've run into a sticky problem that I can't seem to solve with java generics. This is a bit complicated, but I couldn't think of a simpler scenario to illustrate the problem... Here goes:
I have a Processor class that requires a Context. There are different types of Context; most processors just need any abstract Context, but others require a specific subclass. Like this:
abstract class AbstractProcessor<C extends Context> {
public abstract void process(C context);
}
class BasicProcessor extends AbstractProcessor<Context> {
#Override
public void process(Context context) {
// ... //
}
}
class SpecificProcessor extends AbstractProcessor<SpecificContext> {
#Override
public void process(SpecificContext context) {
// ... //
}
}
Ok, cool: Processors can declare the type of Context they need, and they can assume the right type will be passed into process() without casting.
Now, I have a Dispatcher class that owns a mapping of Strings to Processors:
class Dispatcher<C extends Context> {
Map<String, AbstractProcessor<? super C>> processorMap = new HashMap<String, AbstractProcessor<? super C>>();
public void registerProcessor(String name, AbstractProcessor<? super C> processor) {
processorMap.put(name, processor);
}
public void dispatch(String name, C context) {
processorMap.get(name).process(context);
}
}
Ok, so far so good! I can create a Dispatcher for a specific type of Context, then register a batch of processors that may expect any abstraction of that Context type.
Now, here's the problem: I want the abstract Context type to own the Dispatcher, and derived Context types should be able to register additional Processors. Here's the closest I could find to a working solution, but it doesn't fully work:
class Context<C extends Context> {
private final Dispatcher<C> dispatcher = new Dispatcher<C>();
public Context() {
// every context supports the BasicProcessor
registerProcessor("basic", new BasicProcessor());
}
protected void registerProcessor(String name, AbstractProcessor<? super C> processor) {
dispatcher.registerProcessor(name, processor);
}
public void runProcessor(String name) {
dispatcher.dispatch(name, this); // ERROR: can't cast Context<C> to C
}
}
// this is totally weird, but it was the only way I could find to provide the
// SpecificContext type to the base class for use in the generic type
class SpecificContext extends Context<SpecificContext> {
public SpecificContext() {
// the SpecificContext supports the SpecificProcessor
registerProcessor("specific", new SpecificProcessor());
}
}
The problem is that I need to declare a generic Dispatcher in the base Context class, but I want the type-variable to refer to the specific derived type for each Context sub-type. I can't see a way to do this without duplicating some code in each Context subclass (specifically, the construction of the Dispatcher and the registerProcessor method). Here's what I think I really want:
Dispatcher<MyRealClass> dispatcher = new Dispatcher<MyRealClass>();
Is there a way to declare the generic type of an object with the type of the SUBCLASS of the declaring class?
Yes, I can address this problem with a little bit of low-risk casting, so this is mostly an academic question... But I'd love to find a solution that just works top-to-bottom! Can you help? How would you approach this architecture?
UPDATE:
Here's the full source, updated to incorporate Andrzej Doyle's suggestion to use <C extends Context<C>>; it still doesn't work, because Context<C> != C:
class Context<C extends Context<C>> {
private final Dispatcher<C> dispatcher = new Dispatcher<C>();
public Context() {
// every context supports the BasicProcessor
registerProcessor("basic", new BasicProcessor());
}
protected void registerProcessor(String name, AbstractProcessor<? super C> processor) {
dispatcher.registerProcessor(name, processor);
}
public void runProcessor(String name) {
dispatcher.dispatch(name, this); // ERROR: can't cast Context<C> to C
}
}
// this is totally weird, but it was the only way I could find to provide the
// SpecificContext type to the base class for use in the generic type
class SpecificContext extends Context<SpecificContext> {
public SpecificContext() {
// the SpecificContext supports the SpecificProcessor
registerProcessor("specific", new SpecificProcessor());
}
}
abstract class AbstractProcessor<C extends Context<C>> {
public abstract void process(C context);
}
class BasicProcessor extends AbstractProcessor {
#Override
public void process(Context context) {
// ... //
}
}
class SpecificProcessor extends AbstractProcessor<SpecificContext> {
#Override
public void process(SpecificContext context) {
// ... //
}
}
class Dispatcher<C extends Context<C>> {
Map<String, AbstractProcessor<? super C>> processorMap = new HashMap<String, AbstractProcessor<? super C>>();
public void registerProcessor(String name, AbstractProcessor<? super C> processor) {
processorMap.put(name, processor);
}
public void dispatch(String name, C context) {
processorMap.get(name).process(context);
}
}
It sounds like your problem is that you need the generics to refer to the specific exact type of the subclass, rather than inheriting the generic definition from the parents. Try defining your Context class as
class Context<C extends Context<C>>
Note the recursive use of the generic parameter - this is a bit hard to wrap one's head around, but it forces the subclass to refer to exactly itself. (To be honest I don't quite fully get this, but so long as you remember that it works, it works. For reference, the Enum class is defined in exactly the same way.) There's also a section in Angelika Langer's Generics FAQ that covers this.
This way the compiler gets more information about exactly what types are permissable, and should allow your case to compile without the superfluous casting.
UPDATE: Having thought about this a bit more, my above comments were along the right track but were not entirely on the money. With self-recursive generic bounds, as above, you can never really use the actual class you define them on. I'd actually never fully noticed this before, as by luck or judgement I'd apparently always used this in the right point of the class hierarchy.
But I took the time to try and get your code to compile - and realised something. The class with these bounds can never be referred to as itself, it can only ever be referred to in the context of a specific subclass. Consider the definition of BasicProcessor for example - Context appears ungenerified in the generic bounds for AbstractProcessor. To prevent a raw type from appearing, it would be necessary to define the class as:
class BasicProcessor extends AbstractProcessor<Context<Context<Context<...
This is avoided with subclasses because they incorporate the recursiveness in their definition:
class SpecificContext extends Context<SpecificContext>
I think this is fundamentally the problem here - the compiler cannot guarantee that C and Context<C> are the same types because it doesn't have the required special-casing logic to work out that the two are actually an equivalent type (which can only actually be the case when the wilcard chaining is infinite, since in any non-infinite sense the latter is always one level deeper than the first when expanded).
So it's not a great conclusion, but I think in this case your cast is needed because the compiler is unable to derive the equivalence for itself otherwise. Alternatively, if you were using a concrete subclass of Context in a similar position the compiler is able to work it out and this would not be a problem.
If you do happen to find a way to get this working without casting or having to insert a dummy subclass then please report back - but I can't see a way to do that, that would work with the syntax and semantics available to Java's generics.

Categories

Resources