这是Java inherited Fluent method return type in multiple level hierarchies的简化版本。

给出以下代码:

public enum X {
    ;
    static interface BaseFoo<T, S extends BaseFoo<T, S>> {
        S foo();
    }

    static interface Foo<T> extends BaseFoo<T, Foo<T>> {
        void foo1();
    }

    static interface BaseBar<T, S extends BaseBar<T, S>> extends BaseFoo<T, S> {
        S bar();
    }

    static interface Bar<T> extends BaseBar<T, Bar<T>>, Foo<T> {
        void bar1();
    }

}

运行javac X.java我收到错误消息:
X.java:15: error: BaseFoo cannot be inherited with different arguments: <T,X.Bar<T>> and <T,X.Foo<T>>
    static interface Bar<T> extends BaseBar<T, Bar<T>>, Foo<T> {
           ^

有人有什么解决办法吗?

免责声明:我正在尝试使用该模式在整个容器类继承层次结构中实现fluent interface

背景:为了使人们更容易理解我为什么需要它,这里是故事。我想创建一个容器系列:Traversal Sequence List。因此Traversal有一个Traveral<T> accept(Visitor<T>)方法(简称为PECS),该方法应在对元素进行访问者迭代之后始终返回this。当我有List类型时,我希望该方法返回List<T>而不是Traversal<T>,因为我希望可以调用类似myList.accept(v).head(15)的名称,其中head(int)List的方法,而不是Traversal

最佳答案

类或接口不能实现或从通用接口的不同实例扩展。您的Bar接口违反了此规则。让我们检查一下接口声明:

static interface Bar<T> extends BaseBar<T, Bar<T>>, Foo<T>

因此,Bar<T>扩展了两个接口:
  • BaseBar<T, Bar<T>>
  • Foo<T>

  • 除此之外,这两个接口还来自同一接口BaseFoo的不同实例。
  • BaseBar<T, S extends BaseBar<T, S>> extends BaseFoo<T, S>
  • Foo<T> extends BaseFoo<T, Foo<T>>

  • 这些继承的接口最终还是Bar接口的超级接口。因此,您的Bar接口尝试从BaseFoo的2个不同的实例扩展为非法。让我们用一个简单的例子了解原因:
    // Suppose this was allowed
    class Demo implements Comparable<Demo> , Comparable<String> {
        public int compareTo(Demo arg)     { ... }
        public int compareTo(String arg) { ... }
    }
    

    然后在类型擦除之后,编译器将为两种通用方法生成2个桥接方法。该类被翻译为:
    class Demo implements Comparable<Demo> , Comparable<String> {
        public int compareTo(Demo arg)     { ... }
        public int compareTo(String arg) { ... }
    
        // Bridge method added by compiler
        public int compareTo(Object arg)     { ... }
        public int compareTo(Object arg) { ... }
    }
    

    因此,这导致在类中创建重复的桥方法。这就是为什么它是不允许的。

    09-11 18:09