Интерфейсы, наследование и подтипы - PullRequest
0 голосов
/ 22 ноября 2010

У меня есть следующий беспорядок JAVA, который мне очень непонятен:

универсальный интерфейс с двумя универсальными типами A и B, такой как AIter<A,B>

другой универсальный интерфейс с дополнительнымуниверсальный тип C, например: BIter<A,B,C> extends AIter<A,B>

один универсальный класс, ClassA<D>, который рекурсивно реализует первый интерфейс AIter как внутренний класс, например: ThisIter implements AIter<Something,ThisIter>

другой универсальный класс, ClassB<D,E>, который рекурсивно реализует второй интерфейс BIter как внутренний класс, например: ThisIter implements BIter<Something,ThisIter,SomethingElse>

Оба класса имеют функцию с именем public ThisIter giveIter();, которая должна возвращать экземпляр внутреннего класса (каждыйвнутренних классов имеет аналогичную функцию, которая также возвращает новый экземпляр самого себя, но с другим параметром).

Возможно ли реализовать ClassB как подтип ClassA?(Учитывая, что универсальные типы одинаковы, например, ClassA<MyString> и ClassB<MyString, somethingelse>)

Я не могу этого сделать, потому что экземпляры ThisIter и, следовательно, возвращаемые типы giveIter ()несовместимы.

Обычно спрашивается, является ли реализация подынтерфейса (n) когда-либо подтипом реализации самого интерфейса?

IterA

public interface IterA<A,B> {}

IterB

public interface IterB<A,B,C> extends IterA<A,B> {}

Класс A:

public class ClassA<L> {
    Node root;

    public ClassA() {
        root= new Node();
    }

    protected class Node {
       /*...*/
    }

    protected class Edge {
        /*...*/
        L varL;
    }

    protected class ThisIter implements IterA<Edge,ThisIter> {
    /*...*/
    }
    public IterA<Edge,ThisIter> assoc() {
        return new ThisIter(root);
    }
}

Класс B:

public class ClassB<L,N> {
    Node root;

    public ClassB() {
        root= new Node();
    }

    protected class Node {
       /*...*/
       N varN;
    }

    protected class Edge {
        /*...*/
       L varL;
    }

    protected class ThisIter implements IterB<Edge,ThisIter,N> {
    /*...*/
    }
    public IterB<Edge,ThisIter,N> assoc() {
        return new ThisIter(root);
    }
}

Ответы [ 3 ]

1 голос
/ 22 ноября 2010

Мы не можем переопределить внутренние классы. Читайте здесь о Можно ли переопределить внутренние классы .

Q. Возможно ли реализовать ClassB как подтип ClassA?

а. Да, вам нужно выбрать другое имя для вашего ClassB.getIter(). В противном случае он будет жаловаться на то, что переопределенный метод имеет другой тип возвращаемого значения или что-то в этом роде. На самом деле, вы не намерены переопределять это, но компилятор не знает этого. Следовательно, вам нужно выбрать другое имя для него.

Q. Обычно задается вопрос, является ли реализация подынтерфейса (n) когда-либо подтипом реализации самого интерфейса?

A. Нет, в этом случае это будут две разные иерархии классов. Один сверху вниз, interfaceA -> interfaceB -> classD, а другой interfaceA -> classC.

0 голосов
/ 22 ноября 2010

Не уверен, поможет ли это, но следующие компиляции

interface AIter<A,B>{}
interface BIter<A,B,C,D extends A,E extends B > extends AIter<A,B>{}

class AClass{
    protected class Node {}
    protected class Edge {}

    public class ThisIter implements AIter<Node,Edge>{};

    public ThisIter getIter(){
        return new ThisIter();
    }
}

class BClass<N> extends AClass{
    protected class Node extends AClass.Node{}
    protected class Edge extends AClass.Edge{}

    public class ThisIter extends AClass.ThisIter implements BIter<AClass.Node,AClass.Edge, N, Node, Edge>{};

    @Override
    public ThisIter getIter(){
        return new ThisIter();
    }
}
0 голосов
/ 22 ноября 2010

Пересмотрите свое именование и факторинг кода, в частности, вам действительно нужен класс с именем node и edge в каждом из ваших контейнерных классов?

Вот что-то компилируемое, напоминающее ваш код (насколько я понимаю, намерение.)

    interface IterA<A,B> {}
    interface IterB<A,B,C> extends IterA<A,B> {}

    class ClassA<L> {
        NodeA root;
        public ClassA() { root= new NodeA(); }
        protected class NodeA { }
        protected class EdgeA { L varL; }
        protected class ThisIterA implements IterA<EdgeA, ThisIterA> { ThisIterA(NodeA root) { } }

        public IterA<? extends EdgeA, ? extends IterA> assoc() { return new ThisIterA(root); }
    }

    class ClassB<L,N> extends ClassA<L> {
        NodeB root;
        public ClassB() { root= new NodeB(); }
        protected class NodeB extends NodeA { N varN; }
        protected class EdgeB extends EdgeA { L varL; }
        protected class ThisIterB<EA extends EdgeA, TIA extends IterB> implements IterB<EA, TIA, N> { ThisIterB(NodeB root) { } }

        public IterB<EdgeB, IterB, N> assoc() { return new ThisIterB<EdgeB, IterB>(root); }
    }

Уже поздно, так что это последний из меня. Удачи и спокойной ночи!

...