简体   繁体   中英

Using a generic type with a wildcard for its own type

This is my first question here on Stackoverflow, so if I'm doing something wrong, please tell me so I can improve it the next time.

Since it's been a while since I've done some programming in Java and even then only some simple stuff, I'm still learning a lot about a lot off features and find it helpful to read discussions on this site.

I thought I understood the way Generics worked until I faced the following problem. I understand it isn't the nicest design or there are ways to solve it in another way, but let's say it must be done this way.
(It is intended as a low layer in the application, so I liked Generics to make a connection with the layer on top.)

Situation
A base class Identifieable is extended by Groupable , a class which can be extended by an Item , Mutation , Location , etc.

As groups must be made of these things, I added:

class Group<T extends Groupable> extends Groupable
{ 

    public Group(Id id)
    {
        super(id);
        content = new HashMap<T, Integer>();
    }

    private final HashMap<T, Integer> content;
            // Additional methods for adding, removing etc.
}

I added the Generic here to restrict to be able to restrict a group to items, mutations, etc. A group must be groupable too.

As I want to be able to know which groups I am part of I designed my Groupable as follows:

    class Groupable extends Identifieable
    {

        public Groupable(Id id)
        {
            super(id);
            partOf = new ArrayList<Group<? extends Groupable>>();
        }

        private ArrayList<Group<? extends Groupable>> partOf;

        private final ArrayList<Group<? extends Groupable>> containingGroups()
        {
              return partOf;
        }
    }

Problem
The Generic type of 'partOf' is what pains me. I need to return a list of groups of a type which extends Groupable (of course), and indirectly supers the class this object is an instance of. A Mutation cannot be part of a list of Items of course.

I've considered using a type parameter in Groupable, but this does not seem correct to me. That way you instantiate an Item which has it's class as a type for it's parent, which is possible but not nice. This way it is possible to return and store Groups of its own type but not Groups of super-type.

Finally
I don't know if this is clear, I really don't know how to simplify the problem with preserving all elements.

If a brilliant problem-solving design exists which keeps in mind all these classes are meant to be extended and used in an as "generic" ;) manner possible, many thanks.

I've read about just using raw type, but that doesn't seem right although it is already safe to assume no bad casting would happen. If someone can explain what Java does with this Generic-nesting with wildcards and the correct way to solve this specific problem, again many thanks.

I'm more interested in a correct way, or theoretical explanation than a workaround, don't have errors yet, because I don't know how to implement it.

You cannot prescribe to the Groupable class to contain a collection of Groups. The primary reason it is so is that the Group class extends Groupable, and therefore it is not (cannot be) known at the time when the Groupable class is compiled.

There other issue here is that it does not really make sense (to me). For instance, what if the Groupable class was extended by the Item class. Would it make sense for it to contain a collection of Groups - taking into account that it would basically be its sibling but the only thing that would connect them is a common parent.

I would suggest to modify the code this way:

class Groupable extends Identifiable
{
    private ArrayList<? extends Groupable> partOf;

    public Groupable(String id)
    {
        partOf = new ArrayList<Groupable>();
    }


    private final ArrayList<? extends Groupable> containingGroups()
    {
          return partOf;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM