Common Feedback Interface

I want to create two interfaces with inverse relationships.

public interface Item <D extends Description, C extends Category<D,Item<D,C>>> { public C getCategory(); public void setCategory(C category);} 

I am not sure if the expression C extends Category<D,Item<D,C>> correct, but at least there are no compiler errors.

 public interface Category<D extends Description, I extends Item> { public List<I> getItems(); public void setItems(List<I> items);} 

I extends Item issues a warning Item is a raw type. References to Item<D,C> should be parametrized Item is a raw type. References to Item<D,C> should be parametrized . I tried

 I extends Item<D,Category<D,I>> 

but this leads to a Bound mismatch: The type Category<D,I> is not a valid substitute for the bounded parameter <C extends Category<D,Item<D,C>>> of the type Item<D,C> error Bound mismatch: The type Category<D,I> is not a valid substitute for the bounded parameter <C extends Category<D,Item<D,C>>> of the type Item<D,C> . How to correctly parameterize the Category interface using generics?

+6
source share
5 answers

It seems to work :). I have no idea how to explain this (I usually try to avoid such actions), but here it is:

 interface Description {} interface Item<D extends Description, I extends Item<D, I, C>, C extends Category<D, C, I>> { public C getCategory(); public void setCategory(C category); } interface Category<D extends Description, C extends Category<D, C, I>, I extends Item<D, I, C>> { public List<I> getItems(); public void setItems(List<I> items); } class DescriptionImpl implements Description {} class CustomItem implements Item<DescriptionImpl, CustomItem, CustomCategory> { public CustomCategory getCategory() { return null; } public void setCategory(CustomCategory category) { } } class CustomCategory implements Category<DescriptionImpl, CustomCategory, CustomItem> { public List<CustomItem> getItems() { return null; } public void setItems(List<CustomItem> items) { } } 

Now if you do this:

 CustomCategory customCategory = new CustomCategory(); CustomItem customItem = new CustomItem(); DescriptionImpl description = new DescriptionImpl(); customItem.getCategory(); 

the type of category returned by customItem.getCategory() is CustomCategory, which I think you really need.

+2
source

This compiles without warning:

 interface Description {} interface Item<D extends Description, C extends Category<D, Item<D, C>>> { public C getCategory(); public void setCategory(C category); } public interface Category<D extends Description, I extends Item<D, ?>> { public List<I> getItems(); public void setItems(List<I> items); } 

I did I extends Item<D, ?> . Although it does not have any warnings, it may cause other problems - let me know if this happens and I will see what I can do.

0
source

First, forget about the description and just create pretty symmetrical interfaces:

  interface Item<C extends Category<Item<C>>> {} interface Category<I extends Item<Category<I>>> {} 

For descriptions, you may need two different types of descriptions for the item and category.

More generally, I'm not sure if your design is a good idea. I donโ€™t know what you will use it for, but it seems like it will be difficult to use it correctly.

In addition, something looks wrong with item.setCategory(c) , because item already parameterized by category.

0
source

Consider this simplified task.

 interface Item<C extends Container<Item<C>>> interface Container<I extends Item<Container<I>>> 

This does not work because the subtypes of Container<Item<C>> quite limited - Container<MyItem> not a subtype of this, just as List<string> not a subtype of List<Object>

We can relax it with wildcards:

 interface Item<C extends Container<? extends Item<C>>> interface Container<I extends Item<? extends Container<I>>> 

Now it works great

 class MyItem implements Item<MyContainer> class MyContainer implements Container<MyItem> 

primarily. The following announcement is also allowed, but not what we intended

 class HerItem implements Item<MyContainer> // nooo! 

This is because we have relaxed the restrictions too much. Well, this is not a very serious problem. Of course, our type system is not as dense as we want (there is no type system), but programmers will instinctively follow the intended restrictions, do not go out of their way to write fancy things just because they can.

Ideally, we need a type of This , and our alleged limitations can be expressed as

 interface Item<C extends Container<This>>> interface Container<I extends Item<This>> 

Since we donโ€™t have This , we can try to get closer to it using a parameter

 interface Item<C extends Container<This, C>>, This extends Item<C, This> > interface Container<I extends Item<This, I>, This extends Container<I, This>> 

(or, more symmetrically

  interface Item<C extends Container<I, C>>, I extends Item<C, I> > interface Container<I extends Item<C, I>, C extends Container<I, C>> 

) However, this is also not very difficult. This is not really "this type." maybe

 class HerItem implements Item<MyContainer, MyItem> // uh? 

Again, we must rely on the discipline of the programmer to not do this.

0
source

Source: https://habr.com/ru/post/894629/


All Articles