0

So, I have this public interface NodeLevel<E extends NodeLevelEnum>, which has methods public E getParent() and public E getEnum(). An implementing abstract public class NodeLevelAbstract<E extends NodeLevelEnum> implements NodeLevel<E> delegates to instances of class A that implements public interface NodeLevelEnum<E extends NodeLevelEnum>. The last declaration should mean that instances of classes that implement NodeLevelEnum can do something with instances of classes that implement NodeLevelEnum.

Now, this is NodeLevelAbstract#getParent():

@Override
public E getParent() {
    return this.getEnum().getParent();
}

Results in a compiler error (I use NetBeans 7.2, btw):

incompatible types
required: E
found:    NodeLevelEnum
where E is a type-variable:
E extends NodeLevelEnum declared in class NodeLevelAbstract

To me, this means that a descendant of NodeLevelEnum is required, but NodeLevelEnum is found, which, given that the bound in Java Generics includes itself, sounds like absolute bollocks.

Why are these types incompatible? And is there any graceful way to do what I mean to do? Thanks in advance. =)

Update 1

Btw, NodeLevelEnum#getParent() returns <E extends NodeLevelEnum>, and not NodeLevelEnum, which the error says it does.

Update 2

abstract public class NodeLevelAbstract<E extends NodeLevelEnum> implements
        NodeLevel<E> {

    protected E _enum;

    @Override
    public E getEnum() {
        return this._enum;
    }

    @Override
    public E getParent() {
        return this.getEnum().getParent();
    }

    public static <E extends NodeLevelEnum<E>> E[] getEnumLineage(E _enum) {
        ArrayList<E> ancestors = new ArrayList<>();
        E currentEnum = _enum;
        do {
            ancestors.add(currentEnum);
            currentEnum = currentEnum.getParent();
        } while (currentEnum != null);
        return (E[]) ancestors.toArray();
    }

    public static <E extends NodeLevelEnum<E>> HashMap<String, String>
        getEnumLineageValueMap(
            E _enum) {
        HashMap<String, String> map = new HashMap<>();
        for (E e : getEnumLineage(_enum)) {
            map.put(e.getCode(), e.getValue());
        }
        return map;
    }
}

public interface NodeLevel<E extends NodeLevelEnum> {

    public E getEnum();

    public E getParent();
}

public interface NodeLevelEnum<E extends NodeLevelEnum> {

    public E getParent();
}

public interface FilestructureLevel<E extends NodeLevelEnum<E>> extends
        NodeLevel<E> {

    public String getPathPrefix();
}

public class FileLevel<E extends NodeLevelEnum<E>> extends NodeLevelAbstract<E>
        implements FilestructureLevel<E> {

    protected String _pathPrefix;

    @Override
    public String getPathPrefix() {
        return this._pathPrefix;
    }

    public HashMap<String, String> getValueMap(Boolean withPath) {
        return getEnumLineageValueMap(this.getEnum(), withPath);
    }

    public static <E extends NodeLevelEnum<E>> HashMap<String, String>
        getEnumLineageValueMap(
            E _enum) {
        return getEnumLineageValueMap(_enum, false);
    }

    public static <E extends NodeLevelEnum<E>> HashMap<String, String>
        getEnumLineageValueMap(
            E _enum, Boolean withPath) {
        HashMap<String, String> map = new HashMap<>();
        FileLevelEnum[] lineage = (FileLevelEnum[]) getEnumLineage(_enum);
        for (FileLevelEnum e : lineage) {
            String value = !withPath ? e.getValue() : e.getPathPrefix()
                + e.getValue();
            map.put(e.getCode(), value);
        }
        return map;
    }
}
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
XedinUnknown
  • 677
  • 9
  • 25
  • 4
    So have you tried changing `NodeLevel` to `NodeLevel>`? – OldCurmudgeon Mar 28 '13 at 16:56
  • 1
    Your question would be a little easier to read if you just posted a (minimal) version of your interface and class, rather than trying to describe them in prose! – Oliver Charlesworth Mar 28 '13 at 16:58
  • Your first comment worked. Could you explain please..? – XedinUnknown Mar 28 '13 at 16:59
  • @XedinUnknown - See [this](http://stackoverflow.com/q/211143/823393) question. – OldCurmudgeon Mar 28 '13 at 17:04
  • @XedinUnknown - and [this](http://madbean.com/2004/mb2004-3/) is especially good. – OldCurmudgeon Mar 28 '13 at 17:06
  • @OldCurmudgeon, so from the awesome link #1 that you gave, I can conclude that _the type argument for `NodeLevelAbstract` has to derive from a `NodeLevelEnum` which itself has the same type argument_. I think it is going to take some time for me to fully understand this sentence, but my subconscious mind tells me it makes sense. Thank you =) – XedinUnknown Mar 28 '13 at 17:16
  • @XedinUnknown - or, perhaps more simply *an `enum` is an `Enum` of itself*. – OldCurmudgeon Mar 28 '13 at 17:22
  • BTW, I only had to create this wrapper because I stumbled upon a similar article before, from which I found out that Enums cannot extend, only implement. This is sad, and has lead me to tear lots of hair from my behind. – XedinUnknown Mar 28 '13 at 17:22
  • So, I am stuck again. I need to narrow the generic type in `FileLevel` so that the type is `>`, and the same for the 2 static functions, because I need them to accept this type. I already understand that they cannot override the static methods in `NodeLevelAbstract`, only overload. I understand that this new narrowed-down generic type should be the type parameter for `FileLevel`, or, even better, for `FilestructureLevel`, but when I change it to `>`, it, obviously, breaks the inheritance. – XedinUnknown Mar 29 '13 at 07:29
  • Add your new question to your question instead of a comment. Provide the definition of FileLevelEnum. Try not to introduce a horizontal scroll bar. Stop using arrays with generics code. Also : https://www.google.com/search?hl=en&q=java+programming+to+the+interface. Get rid of `HashMap` parameters/return types - use `Map`' – Mr_and_Mrs_D Oct 19 '13 at 12:26

0 Answers0