Java继承多级层次结构中的Fluent方法返回类型

标签 java generics inheritance fluent fluent-interface

因此遵循 Java - Inherited Fluent method return type to return incident class' type, not parent's 中描述的解决方案。我想将其扩展到多个级别。

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

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

知道如何解决这个问题吗?

最佳答案

这是您的继承层次结构:

inheritance hierarchy

正如您所看到的,其中一些类型多次继承相同的接口(interface)类型。事实上,BarImpl实现BaseFoo四次以上,并且某些继承链为其类型参数S提供不同的参数。 。可以说BarImpl实现以下内容:

  • BaseFoo<T, Foo<T>> (来自Foo)
  • BaseFoo<T, Foo<T>> (来自FooImpl)
  • BaseFoo<T, Bar<T>> (来自Bar)
  • BaseFoo<T, Bar<T>> (来自BarImpl)

The same interface cannot be implemented with different type arguments ,因此您会收到编译器错误。

正如我在您的后续问题中指出的那样,我的回答 here讨论如何正确模拟“ self 类型”来实现分层流畅的构建器模式,就像您尝试做的那样。在其中,我指出需要在所有中间类型中维护一个变量“ self 类型”(代码中的 S ) - 仅使用被理解为 final 的“叶类”来解析它。 。您的代码违反了该规则,因为中间类型 Foo , Bar ,和FooImpl过早解决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 .
  • main ,声明foobarFooImplBarImpl - 接口(interface)编码在这里不可行。

关于Java继承多级层次结构中的Fluent方法返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19417082/

相关文章:

c++ - 为什么基类函数没有被同名的派生类函数隐藏

java - mybatis POOLED 数据源

java - Spring捕获所有响应类型

java - 在 for 循环的条件语句中使用 vector.size() 时出现无限循环

C# 泛型类型 typedef/alias 和 InvalidCastException

Swift:覆盖属性类

表示单继承的 C++ 数据结构

java - 简单的 mysql/jdbc 代码导致内存泄漏?

scala按类型过滤

java - Java继承中的私有(private)成员