1

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.

Community
  • 1
  • 1
Haggra
  • 3,539
  • 2
  • 20
  • 28
  • 15
    What good could possibly come out of allowing this? – Tunaki Feb 08 '16 at 12:53
  • ...couldn't you just merge them together completely or have a common base if you want that? – EpicPandaForce Feb 08 '16 at 12:56
  • There could be very rare cases where each interfaces suits the "is-a" rule, thus can extend each other. That's not the case. Why is this not allowed? Does this possess any danger to program? Not because I'm going to use it for sure but because there could be something I'm going to learn from this. – Haggra Feb 08 '16 at 12:58
  • a superclass must be a class – Greesh Kumar Feb 08 '16 at 12:59
  • 3
    If `Foo extends Bar`, then every instance of `Foo` is also a `Bar`. If `Bar extends Foo`, then every instance of `Bar` is also a `Foo`. If both were allowed to be true, then the only way the two conditions can be satisfied is if `Foo == Bar`. – Andy Turner Feb 08 '16 at 13:00

3 Answers3

3

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.

christopher
  • 26,815
  • 5
  • 55
  • 89
1

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 produce benefits.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
1

See Java Language Specification 9.1.3 Superinterfaces and Subinterfaces :

An interface I depends on a reference type T if any of the following is true:

  • I directly depends on T.

  • I directly depends on a class C that depends on T (§8.1.5).

  • I directly depends on an interface J that depends on T (using this definition recursively).

It is a compile-time error if an interface depends on itself.

If circularly declared interfaces are detected at run time, as interfaces are loaded, then a ClassCircularityError is thrown (§12.2.1).

As for why, I like Andy Turner's comment:

If Foo extends Bar, then every instance of Foo is also a Bar. If Bar extends Foo, then every instance of Bar is also a Foo. If both were allowed to be true, then the only way the two conditions can be satisfied is if Foo == Bar.

Community
  • 1
  • 1
Andreas
  • 154,647
  • 11
  • 152
  • 247