Haggra February 2016

Cyclic Inheritance Of Interfaces

I understand why cyclic inheritance of classes is not allowed in Java but I did not understand why cyclic inheritance of interfaces is not allowed. To illustrate:

interface Foo extends Bar {/*methods and constants*/}

interface Bar extends Foo {/*methods and constants*/}

Interfaces do not need instantiation, then what prevents them from extending each other?

By the way, I read this question but this is not about interfaces but classes: Cyclic inheritance hierarchy in Java

Thanks in advance.

Answers


christopher February 2016

No, but extension of an interface is a way of splitting up the agreement. Remember, an interface is an agreement to provide an implementation of a set of methods.

public interface A extends B {
    public void myMethod();
    public void myOtherMethod();
}

You're saying interface A is defined by these methods and all the methods in interface B. Now if interface B says..

public interface B extends A {}

you're saying that interface B is defined by the methods in interface A. Well what defines interface A. A couple of methods and interface B. And what defines interface B? Interface A, which is defined by a couple of methods and interface B! See where this is going?

It makes no logical sense to allow this.


Tagir Valeev February 2016

Probably there are no theoretical difficulties, but this would create unnecessary complications. A few to name:

  • Currently traversal of class interfaces (via recursive calls of Class.getInterfaces()) is guaranteed to produce finite result, probably with repeats, but nevertheless. For example, such code is valid:

    private static void fillInterfaces(Class<?> clazz, Set<Class<?>> set) {
        if(clazz == null) return;
        for (Class<?> iclass : clazz.getInterfaces()) {
            set.add(iclass);
            fillInterfaces(iclass, set);
        }
        fillInterfaces(clazz.getSuperclass(), set);
    }
    
    public static Set<Class<?>> getAllInterfaces(Class<?> clazz) {
        Set<Class<?>> result = new HashSet<>();
        fillInterfaces(clazz, result);
        return result;
    }
    

    Similar code is already written and working in many places. With your proposal supplying the circular interface here would cause an infinite recursion.

  • Currently (in Java-8) interface can define a default implementation for its parent interface as well, replacing parent implementation if necessary. For example:

    interface A {
        default public String getX() {return "A";}
    }
    
    interface B extends A {
        default public String getX() {return "B";}
    }
    
    static class C implements A, B {} // ok, C.getX() returns "B"
    

    If now A extends B, then A wins:

    interface A extends B {
        default public String getX() {return "A";}
    }
    
    interface B {
        default public String getX() {return "B";}
    }
    
    static class C implements A, B {} // ok, C.getX() returns "A"
    

    But what if both A extends B and B extends A? Who will win? What new C().getX() will print? Or should it be new type of compilation error?

In general it seems that such feature would bring more problems than pr

Post Status

Asked in February 2016
Viewed 3,222 times
Voted 7
Answered 2 times

Search




Leave an answer