【问题标题】:Return class that extends abstract class返回扩展抽象类的类
【发布时间】:2021-11-12 17:46:33
【问题描述】:

我正在尝试实现 Fluet 接口模式。所以基本上这个想法是有链接方法,但我是 将它与策略模式混合,所以我可以有多个“Foo”的实现

我有这个抽象类:

public abstract class Foo<T extends BarData> {
    T data;

    public Foo(T data) {
        this.data = data;
    }

    public Foo<T> fooMethod {
        // do stuff with data
        return this;
    }
}

这是另一个提供另一种方法的 Foo 实现:

public class Bar extends Foo<BarData> {

    public Bar(BarData data) {
        super(data);
    }

    public Bar barMethod() {
        // do more stuff with data
        return this;
    }
}

流畅的界面:

public interface FluentInterface<T extends BarData, S extends Foo<T>> {

    S initialize();
}

基本实现:

public class BasicFluentInterfaceImplementation implements FluentApi<BarData, Bar> {

    @Override
    Bar initialize() {
        // prepares data
        return new Bar(data);
    }
}

一起使用:

public class Main {
    public static void main(String[] str) {
        FluentInterface api = new BasicFluentInterfaceImplementation();

        var firstReturn = api.initialize(); // Here it returns Bar

        var secondReturn = firstReturn.fooMethod(); // As Bar extends Foo i can call the fooMethod()

        var thirdReturn = secondReturn.barMethod(); // Here is the problem, i can't call the barMethod, because fooMethod already returned an intance of Foo
    }
}

如何让 Foo 返回 Bar 的实例?考虑到 Bar 可以是任何扩展 Foo 的东西。

【问题讨论】:

  • 我想你想要class Bar&lt;T extends BarData&gt; extends Foo&lt;T&gt;
  • 你不能。您的FluentInterface#initializeFoo#fooMethod 都返回Foo,这就是游戏结束的地方。
  • 另外,只是一个警告:小心使用var 和泛型。您可能很难使用通配符捕获。

标签: java generics


【解决方案1】:

我有很多坏消息;这个问题没有真正的解决方案。流利的接口确实不错,但是您在问题中描述的这种情况表明在这里不值得这样做,因为现在主要是令人困惑,您不能从fooMethod 链接到barMethod 的调用。对于这样的层次结构,最好只恢复到void-returning 方法。

IS 有一个可用的 hack,但是,它.. 很乱。

public abstract class Foo<T extends BarData, Z extends Foo<T>> {
    T data;

    public Foo(T data) {
        this.data = data;
    }

    public Z fooMethod() {
        // do stuff with data
        return self();
    }

    @SuppressWarnings("all")
    protected Z self() {
        return (Z) this;
    }
}

Z 这里的意思是表示“自我”,无论对象实际上是什么类型,即使在超类型的定义中也是如此。换句话说,对于 Bar 的实例,self() 的返回类型应该是 Bar,即使它是在 Foo 中定义的。

不幸的是,在定义子类型时,您必须“弄乱”Z 的东西:class Bar extends Foo&lt;BarData, Bar&gt; {}。第二个参数总是你自己的类型,它'使它工作'。

这个 hack 对你来说值得吗?由你决定。假设是,请不要太仓促。

【讨论】:

  • 是的,我试过了,但因为演员表而不想使用。没有真正得到第一个想法,你的意思是像返回下一个方法?
  • 不,不返回任何内容 - 无效。没有可链接的 API - 不值得麻烦。就是这样,或者这个答案中显示的 sn-p 。请注意,只需要一个执行强制转换的方法(方法self())。所有其他人都可以调用self();无需投射。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多