简体   繁体   中英

Accessing generic container from abstract item-class in java

I'm trying to implement a container which is generic about it's items. All possible item classes share a single abstract base class which provides access to the surrounding container.

The following code shows my simplest approach:

public class GenericContainerProblem {

    public static void main(String[] args) {
        Container<SpecificItem> container = new Container<>();
        new SpecificItem(container);
    }

    private static class Container<ItemType extends AbstractItem> {
        private final List<ItemType> list = new ArrayList<>();

        public Container() {
            //
        }

        protected void addItem(ItemType specificItem) {
            list.add(specificItem);
        }
    }

    private static abstract class AbstractItem {
        protected final Container<? extends AbstractItem> container;

        public AbstractItem(Container<? extends AbstractItem> container) {
            this.container = container;
            container.addItem(this); // fails *
        }
    }

    private static class SpecificItem extends AbstractItem {
        public SpecificItem(Container<SpecificItem> container) {
            super(container);
            container.addItem(this); // succeeds
        }
    }

}

*) Error: The method addItem(capture#3-of ? extends GenericContainer.AbstractItem) in the type GenericContainer.Container<capture#3-of ? extends GenericContainer.AbstractItem> is not applicable for the arguments (GenericContainer.AbstractItem) The method addItem(capture#3-of ? extends GenericContainer.AbstractItem) in the type GenericContainer.Container<capture#3-of ? extends GenericContainer.AbstractItem> is not applicable for the arguments (GenericContainer.AbstractItem)

This doesn't work as is because of the possible type mismatch allowed by the declaration ? extends AbstractItem ? extends AbstractItem . I think I need some type constraints telling the compiler the Container<?> -type used within AbstractItem is valid for this .

How can I declare/call the AbstractItem -class (and its constructor) in a way that it can access the container which is generic about a specific sub-class?

As far as I know, you need to make AbstractItem generic, in order to specify the type of the container it uses. You'd also need to use an unchecked cast in the AbstractItem constructor.

But are you really sure you want such a bidirectional association between the container and the containee? Perhaps you should rethink this design.

public class GenericContainerProblem {

    public static void main(String[] args) {
        Container<SpecificItem> container = new Container<>();
        new SpecificItem(container);
    }

    private static class Container<ItemType extends AbstractItem<ItemType>> {
        private final List<ItemType> list = new ArrayList<>();

        public Container() {
            //
        }

        protected void addItem(ItemType specificItem) {
            list.add(specificItem);
        }
    }

    private static abstract class AbstractItem<T extends AbstractItem<T>> {
        protected final Container<T> container;

        public AbstractItem(Container<T> container) {
            this.container = container;
            container.addItem((T) this);
        }
    }

    private static class SpecificItem extends AbstractItem<SpecificItem> {
        public SpecificItem(Container<SpecificItem> container) {
            super(container);
            container.addItem(this);
        }
    }

}

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