2

因此,按照Java - Inherited Fluent method return type 中描述的解决方案返回事件类的类型,而不是父级的. 我想将它扩展到多个级别。

该解决方案显然在一个级别上有效。这是已编译和可运行的代码(无依赖关系):

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 abstract class AbstractFooBase<T, S extends BaseFoo<T, S>> implements BaseFoo<T, S> {
        abstract void internalFoo();
        @Override
        public S foo() {
            internalFoo();
            return (S)this;
        }
    }

    static class FooImpl<T> extends AbstractFooBase<T, Foo<T>> implements Foo<T> {
        @Override
        void internalFoo() {
            System.out.println("inside FooImpl::internalFoo()");
        }

        @Override
        public void foo1() {
            System.out.println("inside FooImpl::foo1()");
        }
    }

    public static void main(String[] args) {
        Foo<String> foo = new FooImpl<String>();
        foo.foo().foo1();
    }
}

但是,当我在对象继承层次结构中添加一个新级别时,事情变得很困难。下面的代码不会编译:

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>> {
        void bar1();
    }

    static abstract class AbstractFooBase<T, S extends BaseFoo<T, S>> implements BaseFoo<T, S> {
        abstract void internalFoo();
        @Override
        public S foo() {
            internalFoo();
            return (S)this;
        }
    }

    static class FooImpl<T> extends AbstractFooBase<T, Foo<T>> implements Foo<T> {
        @Override
        void internalFoo() {
            System.out.println("inside FooImpl::internalFoo()");
        }

        @Override
        public void foo1() {
            System.out.println("inside FooImpl::foo1()");
        }
    }

    static abstract class AbstractBarBase<T, S extends BaseBar<T, S>> extends FooImpl<T> implements BaseBar<T, S> {
        abstract void internalBar();
        @Override
        public S bar() {
            internalBar();
            return (S)this;
        }
    }

    static class BarImpl<T> extends AbstractBarBase<T, Bar<T>> implements Bar<T> {
        @Override
        void internalBar() {
            System.out.println("inside BarImpl::internalBar()");
        }

        @Override
        public void bar1() {
            System.out.println("inside BarImpl::bar1()");
        }
    }

    public static void main(String[] args) {
        Foo<String> foo = new FooImpl<String>();
        foo.foo().foo1();

        Bar<Boolean> bar = new BarImpl<Boolean>();
        bar.foo().bar1();
    }
}

编译时错误消息是:

X.java:40: X.BaseFoo cannot be inherited with different arguments: <T,S> and <T,X.Foo<T>>
    static abstract class AbstractBarBase<T, S extends BaseBar<T, S>> extends FooImpl<T> implements BaseBar<T, S> {
                    ^
X.java:49: X.BaseFoo cannot be inherited with different arguments: <T,X.Bar<T>> and <T,X.Foo<T>>
    static class BarImpl<T> extends AbstractBarBase<T, Bar<T>> implements Bar<T> {
           ^
Note: X.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors

知道如何解决它吗?

4

1 回答 1

2

这是您的继承层次结构:

继承层次

如您所见,其中一些类型不止一次地继承同一个接口类型。实际上,BarImpl实现BaseFoo了四次,并且一些继承链为其类型参数提供了不同的参数S。可以说BarImpl实现了以下功能:

  • BaseFoo<T, Foo<T>>(通过Foo
  • BaseFoo<T, Foo<T>>(通过FooImpl
  • BaseFoo<T, Bar<T>>(通过Bar
  • BaseFoo<T, Bar<T>>(通过BarImpl

相同的接口不能用不同的类型参数实现,所以你会得到一个编译器错误。

正如我在您的后续问题中指出的那样,我在此处的回答讨论了如何正确模拟“自我类型”以实现分层流畅的构建器模式,就像您尝试做的那样。在其中,我指出需要S在所有中间类型中维护一个变量“self-type”(在您的代码中) - 仅使用被理解为final. 您的代码违反了该规则,因为中间类型Foo,BarFooImpl过早解析S

以下解决方案解决了该问题:

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

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

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

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

static abstract class AbstractFooBase<T, S extends BaseFoo<T, S>> implements BaseFoo<T, S> {
    abstract void internalFoo();
    @Override
    public S foo() {
        internalFoo();
        return (S)this;
    }
}

static abstract class AbstractIntermediateFoo<T, S extends AbstractIntermediateFoo<T, S>> extends AbstractFooBase<T, S> implements Foo<T, S> {
    @Override
    void internalFoo() {
        System.out.println("inside FooImpl::internalFoo()");
    }

    @Override
    public void foo1() {
        System.out.println("inside FooImpl::foo1()");
    }
}

static final class FooImpl<T> extends AbstractIntermediateFoo<T, FooImpl<T>> { }

static abstract class AbstractBarBase<T, S extends AbstractBarBase<T, S>> extends AbstractIntermediateFoo<T, S> implements BaseBar<T, S> {
    abstract void internalBar();
    @Override
    public S bar() {
        internalBar();
        return (S)this;
    }
}

static final class BarImpl<T> extends AbstractBarBase<T, BarImpl<T>> implements Bar<T, BarImpl<T>> {
    @Override
    void internalBar() {
        System.out.println("inside BarImpl::internalBar()");
    }

    @Override
    public void bar1() {
        System.out.println("inside BarImpl::bar1()");
    }
}

public static void main(String[] args) {
    FooImpl<String> foo = new FooImpl<String>();
    foo.foo().foo1();

    BarImpl<Boolean> bar = new BarImpl<Boolean>();
    bar.foo().bar1();
}

我的更改如下:

  • 维持SFoo
  • 维持SBar
  • 拆分FooImpl为以下内容:
    • AbstractIntermediateFoo,即abstract维护S和实现internalFoofoo1
    • FooImpl, 是具体的, final, 并解决S.
  • 使BarImpl final.
  • In main, declare fooand baras FooImpland BarImpl- 对接口的编码在这里是不可行的。
于 2013-10-19T22:38:04.097 回答